# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1305.9.1+1.1063.9.79 -> 1.1305.9.2 # arch/i386/kernel/process.c 1.49.1.1 -> 1.52 # arch/ppc64/kernel/signal.c 1.27.1.1 -> 1.29 # arch/sparc/kernel/module.c 1.10.1.1 -> 1.12 # arch/alpha/kernel/module.c 1.4.1.1 -> 1.6 # include/asm-ppc64/unistd.h 1.20.1.1 -> 1.23 # kernel/ksyms.c 1.203 -> 1.204 # fs/select.c 1.19.1.1 -> 1.21 # include/linux/timex.h 1.5.1.1 -> 1.9 # include/linux/mm.h 1.121 -> 1.122 # arch/arm/kernel/module.c 1.6.1.1 -> 1.8 # drivers/serial/8250.c 1.33 -> 1.34 # drivers/serial/8250_hcdp.c 1.1 -> (deleted) # include/asm-ppc64/processor.h 1.29.1.1 -> 1.31 # drivers/char/drm/i830_dma.c 1.18.1.1 -> 1.20 # include/linux/sched.h 1.151 -> 1.152 # include/asm-ppc64/module.h 1.3.1.1 -> 1.5 # kernel/fork.c 1.123 -> 1.123.1.1 # kernel/sys.c 1.43.1.4 -> 1.45 # kernel/sysctl.c 1.45 -> 1.45.1.1 # include/asm-ppc64/thread_info.h 1.7.1.1 -> 1.9 # arch/ppc64/kernel/chrp_setup.c 1.27.1.1 -> 1.30 # include/asm-i386/thread_info.h 1.11.1.1 -> 1.13 # drivers/char/drm/r128_cce.c 1.12.1.1 -> 1.14 # drivers/char/drm/drm_memory_debug.h 1.1.1.1 -> 1.3 # arch/i386/kernel/traps.c 1.51.1.2 -> 1.53 # drivers/char/drm/drm_memory.h 1.8.1.3 -> 1.10 # drivers/char/drm/radeon_cp.c 1.20 -> 1.21 # include/linux/serial.h 1.8.1.1 -> 1.10 # include/asm-ppc/pgtable.h 1.23 -> 1.24 # include/asm-ppc/thread_info.h 1.7.1.1 -> 1.9 # kernel/time.c 1.11.1.1 -> 1.15 # drivers/char/drm/drm_bufs.h 1.14.1.1 -> 1.16 # kernel/softirq.c 1.39.1.2 -> 1.41 # drivers/acpi/pci_root.c 1.13.1.1 -> 1.15 # arch/ppc/kernel/module.c 1.9 -> 1.10 # arch/ppc64/kernel/ras.c 1.4.1.1 -> 1.6 # include/asm-parisc/thread_info.h 1.2.1.1 -> 1.4 # include/asm-um/thread_info.h 1.3.1.1 -> 1.5 # include/asm-h8300/thread_info.h 1.1.1.1 -> 1.3 # drivers/char/drm/i810_dma.c 1.26.1.1 -> 1.28 # drivers/serial/8250_hcdp.h 1.1 -> (deleted) # include/asm-v850/thread_info.h 1.2.1.1 -> 1.4 # include/linux/pci_ids.h 1.103 -> 1.104 # include/linux/irq.h 1.6.1.1 -> 1.8 # include/linux/moduleloader.h 1.5.1.1 -> 1.7 # include/asm-alpha/unistd.h 1.18.1.2 -> 1.20 # include/asm-m68knommu/thread_info.h 1.2.1.1 -> 1.4 # arch/ppc64/kernel/irq.c 1.25.1.1 -> 1.30 # drivers/acpi/pci_irq.c 1.16.1.2 -> 1.18 # mm/memory.c 1.123.1.2 -> 1.128 # arch/ppc64/kernel/setup.c 1.24.2.1 -> 1.29 # include/asm-arm/thread_info.h 1.6.1.1 -> 1.8 # arch/i386/kernel/module.c 1.10.1.1 -> 1.12 # drivers/serial/Makefile 1.14.1.2 -> 1.16 # include/linux/acpi_serial.h 1.2.1.1 -> 1.4 # drivers/char/mem.c 1.42 -> 1.43 # arch/ppc64/kernel/traps.c 1.16.2.1 -> 1.20 # arch/ppc64/kernel/head.S 1.31.1.1 -> 1.37 # kernel/posix-timers.c 1.17 -> 1.17.1.1 # include/linux/sunrpc/svc.h 1.19.1.1 -> 1.21 # arch/ppc64/kernel/xics.c 1.22.2.1 -> 1.25 # include/linux/sysctl.h 1.47 -> 1.48 # drivers/net/tg3.c 1.72 -> 1.73 # include/linux/smp.h 1.22.1.3 -> 1.24 # arch/v850/kernel/module.c 1.4.1.1 -> 1.6 # arch/ppc64/mm/init.c 1.42.1.1 -> 1.47 # arch/ppc64/kernel/htab.c 1.33.1.1 -> 1.35 # drivers/char/agp/i460-agp.c 1.25 -> 1.26 # arch/ppc64/kernel/process.c 1.31.1.1 -> 1.36 # arch/ppc64/kernel/pci_dma.c 1.14.1.1 -> 1.17 # fs/proc/base.c 1.45 -> 1.46 # mm/mmap.c 1.85 -> 1.86 # include/linux/time.h 1.13.1.1 -> 1.14.1.1 # arch/sparc64/kernel/module.c 1.12.1.1 -> 1.15 # include/asm-i386/unistd.h 1.24.1.1 -> 1.26 # sound/oss/cs4281/cs4281pm-24.c 1.3.1.1 -> 1.5 # arch/ppc64/kernel/asm-offsets.c 1.13.1.1 -> 1.15 # include/asm-m68k/thread_info.h 1.4.1.1 -> 1.6 # Makefile 1.410 -> 1.411 # fs/fcntl.c 1.25.1.3 -> 1.29 # include/asm-s390/thread_info.h 1.4.1.1 -> 1.6 # arch/ppc64/mm/numa.c 1.4.1.1 -> 1.8 # arch/ppc64/kernel/syscalls.c 1.10.1.1 -> 1.12 # drivers/char/agp/backend.c 1.83 -> 1.84 # include/asm-x86_64/thread_info.h 1.12 -> 1.13 # arch/ppc64/kernel/sys_ppc32.c 1.63 -> 1.63.1.1 # include/asm-sparc64/thread_info.h 1.10.1.1 -> 1.12 # arch/ppc64/kernel/prom.c 1.25.2.1 -> 1.29 # include/asm-x86_64/pgtable.h 1.20 -> 1.20.1.1 # kernel/module.c 1.86 -> 1.87 # arch/ppc64/kernel/iSeries_setup.c 1.12.1.1 -> 1.16 # arch/ppc64/kernel/smp.c 1.34.2.1 -> 1.39 # drivers/char/drm/drmP.h 1.23.1.2 -> 1.25 # include/asm-i386/pgtable.h 1.35.1.1 -> 1.37 # net/ipv4/tcp_input.c 1.39 -> 1.40 # include/linux/highmem.h 1.25.1.1 -> 1.27 # arch/ppc64/kernel/pacaData.c 1.6.1.1 -> 1.8 # kernel/sched.c 1.192 -> 1.192.1.1 # drivers/char/agp/hp-agp.c 1.24 -> 1.25 # drivers/acpi/osl.c 1.37 -> 1.38 # arch/alpha/kernel/traps.c 1.24.1.1 -> 1.26 # drivers/char/drm/drm_drv.h 1.20 -> 1.21 # kernel/timer.c 1.57 -> 1.57.1.1 # arch/ppc64/kernel/pci.c 1.30.1.1 -> 1.34 # include/asm-m68k/pgtable.h 1.8 -> 1.9 # arch/ppc64/kernel/misc.S 1.57.1.1 -> 1.61 # drivers/char/drm/mga_dma.c 1.13.1.1 -> 1.15 # arch/s390/kernel/module.c 1.7.1.1 -> 1.9 # drivers/char/drm/mga_drv.h 1.13.1.1 -> 1.15 # arch/x86_64/kernel/module.c 1.7.1.1 -> 1.10 # include/linux/percpu.h 1.5.1.2 -> 1.7 # arch/arm/kernel/process.c 1.28.1.1 -> 1.30 # arch/ppc64/kernel/signal32.c 1.39.1.1 -> 1.41 # include/asm-alpha/thread_info.h 1.5.1.1 -> 1.7 # drivers/serial/Kconfig 1.8.1.1 -> 1.10 # drivers/char/drm/gamma_dma.c 1.12.1.2 -> 1.14 # include/linux/irq_cpustat.h 1.7.1.1 -> 1.9 # include/asm-ppc64/pgtable.h 1.23 -> 1.24 # include/asm-ppc64/mmzone.h 1.10.1.1 -> 1.12 # include/asm-sparc/thread_info.h 1.4.1.1 -> 1.6 # drivers/video/radeonfb.c 1.26.1.3 -> 1.28 # include/asm-ppc64/topology.h 1.7.1.1 -> 1.9 # arch/ppc64/kernel/module.c 1.4.1.1 -> 1.7 # arch/ppc64/kernel/Makefile 1.23.1.1 -> 1.28 # sound/oss/cs4281/cs4281m.c 1.21.1.3 -> 1.23 # arch/ppc64/kernel/align.c 1.8.1.1 -> 1.11 # arch/ppc64/kernel/ioctl32.c 1.30.1.1 -> 1.36 # drivers/scsi/qla1280.c 1.38 -> 1.39 # drivers/char/drm/drm_vm.h 1.23.1.1 -> 1.25 # arch/parisc/kernel/module.c 1.3.1.1 -> 1.4.1.1 # drivers/scsi/sym53c8xx_2/sym_glue.c 1.23 -> 1.24 # diff -Nru a/Makefile b/Makefile --- a/Makefile Thu Jun 19 00:45:34 2003 +++ b/Makefile Thu Jun 19 00:45:34 2003 @@ -213,7 +213,7 @@ NOSTDINC_FLAGS = -nostdinc -iwithprefix include CPPFLAGS := -D__KERNEL__ -Iinclude -CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ +CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -g -O2 \ -fno-strict-aliasing -fno-common AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) diff -Nru a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c --- a/arch/alpha/kernel/traps.c Thu Jun 19 00:45:34 2003 +++ b/arch/alpha/kernel/traps.c Thu Jun 19 00:45:34 2003 @@ -148,7 +148,7 @@ static int kstack_depth_to_print = 24; -void show_stack(unsigned long *sp) +void show_stack(struct task_struct *task, unsigned long *sp) { unsigned long *stack; int i; @@ -174,7 +174,7 @@ void dump_stack(void) { - show_stack(NULL); + show_stack(NULL, NULL); } void diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Thu Jun 19 00:45:34 2003 +++ b/arch/i386/kernel/process.c Thu Jun 19 00:45:34 2003 @@ -212,7 +212,6 @@ */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { - struct task_struct *p; struct pt_regs regs; memset(®s, 0, sizeof(regs)); @@ -228,8 +227,7 @@ regs.eflags = 0x286; /* Ok, create the new process.. */ - p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } /* @@ -518,27 +516,22 @@ asmlinkage int sys_fork(struct pt_regs regs) { - struct task_struct *p; - - p = do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); } asmlinkage int sys_clone(struct pt_regs regs) { - struct task_struct *p; unsigned long clone_flags; unsigned long newsp; - int *parent_tidptr, *child_tidptr; + int __user *parent_tidptr, *child_tidptr; clone_flags = regs.ebx; newsp = regs.ecx; - parent_tidptr = (int *)regs.edx; - child_tidptr = (int *)regs.edi; + parent_tidptr = (int __user *)regs.edx; + child_tidptr = (int __user *)regs.edi; if (!newsp) newsp = regs.esp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); } /* @@ -553,10 +546,7 @@ */ asmlinkage int sys_vfork(struct pt_regs regs) { - struct task_struct *p; - - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); } /* diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Thu Jun 19 00:45:34 2003 +++ b/arch/i386/kernel/traps.c Thu Jun 19 00:45:34 2003 @@ -101,7 +101,7 @@ stack = (unsigned long*)&stack; printk("Call Trace:"); -#if CONFIG_KALLSYMS +#ifdef CONFIG_KALLSYMS printk("\n"); #endif i = 1; @@ -438,7 +438,7 @@ unsigned char reason = get_nmi_reason(); if (!(reason & 0xc0)) { -#if CONFIG_X86_LOCAL_APIC +#ifdef CONFIG_X86_LOCAL_APIC /* * Ok, so this is none of the documented NMI sources, * so it must be the NMI watchdog. diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/Makefile Thu Jun 19 00:45:34 2003 @@ -7,9 +7,9 @@ obj-y := setup.o entry.o traps.o irq.o idle.o \ time.o process.o signal.o syscalls.o misc.o ptrace.o \ align.o semaphore.o bitops.o stab.o htab.o pacaData.o \ - udbg.o binfmt_elf32.o sys_ppc32.o sys32.o ioctl32.o \ + udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o pmc.o rtc.o init_task.o \ - lmb.o pci.o pci_dn.o pci_dma.o + lmb.o pci.o pci_dn.o pci_dma.o cputable.o obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ iSeries_IoMmTable.o iSeries_irq.o \ @@ -19,14 +19,16 @@ mf.o HvLpEvent.o iSeries_proc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ - eeh.o rtasd.o nvram.o + eeh.o rtasd.o nvram.o ras.o # Change this to pSeries only once we've got iSeries up to date obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \ - chrp_setup.o i8259.o ras.o prom.o + chrp_setup.o i8259.o prom.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_PPC_RTAS) += rtas-proc.o obj-$(CONFIG_SCANLOG) += scanlog.o + +CFLAGS_ioctl32.o += -Ifs/ diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c --- a/arch/ppc64/kernel/align.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/align.c Thu Jun 19 00:45:34 2003 @@ -20,6 +20,9 @@ #include #include #include +#include + +void disable_kernel_fp(void); /* asm function from head.S */ struct aligninfo { unsigned char len; @@ -236,12 +239,11 @@ dsisr = regs->dsisr; - /* Power4 doesn't set DSISR for an alignment interrupt */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { - unsigned int real_instr; - if (__get_user(real_instr, (unsigned int *)regs->nip)) - return 0; - dsisr = make_dsisr(real_instr); + if (cur_cpu_spec->cpu_features & CPU_FTR_NODSISRALIGN) { + unsigned int real_instr; + if (__get_user(real_instr, (unsigned int *)regs->nip)) + return 0; + dsisr = make_dsisr(*((unsigned *)regs->nip)); } /* extract the operation and registers from the dsisr */ @@ -309,6 +311,7 @@ /* Doing stfs, have to convert to single */ enable_kernel_fp(); cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr); + disable_kernel_fp(); } else data.dd = current->thread.fpr[reg]; @@ -342,6 +345,7 @@ /* Doing lfs, have to convert to double */ enable_kernel_fp(); cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr); + disable_kernel_fp(); } else current->thread.fpr[reg] = data.dd; diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c --- a/arch/ppc64/kernel/asm-offsets.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/asm-offsets.c Thu Jun 19 00:45:34 2003 @@ -34,6 +34,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -158,6 +159,13 @@ DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); + + /* About the CPU features table */ + DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); + DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); + DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); + DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); + DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); return 0; } diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/chrp_setup.c Thu Jun 19 00:45:34 2003 @@ -62,13 +62,13 @@ #include "open_pic.h" #include #include +#include extern volatile unsigned char *chrp_int_ack_special; void chrp_progress(char *, unsigned short); extern void openpic_init_IRQ(void); -extern void init_ras_IRQ(void); extern void find_and_init_phbs(void); @@ -238,7 +238,6 @@ ppc_md.init_IRQ = xics_init_IRQ; ppc_md.get_irq = xics_get_irq; } - ppc_md.init_ras_IRQ = init_ras_IRQ; ppc_md.init = chrp_init2; @@ -253,6 +252,34 @@ ppc_md.progress = chrp_progress; + /* build up the firmware_features bitmask field + * using contents of device-tree/ibm,hypertas-functions. + * Ultimately this functionality may be moved into prom.c prom_init(). + */ + struct device_node * dn; + char * hypertas; + unsigned int len; + dn = find_path_device("/rtas"); + cur_cpu_spec->firmware_features = 0; + hypertas = get_property(dn, "ibm,hypertas-functions", &len); + if (hypertas) { + while (len > 0){ + int i; + /* check value against table of strings */ + for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) { + if ((firmware_features_table[i].name) && (strcmp(firmware_features_table[i].name,hypertas))==0) { + /* we have a match */ + cur_cpu_spec->firmware_features |= (1UL << firmware_features_table[i].val); + break; + } + } + int hypertas_len = strlen(hypertas); + len -= hypertas_len +1; + hypertas+= hypertas_len +1; + } + } + udbg_printf("firmware_features bitmask: 0x%x \n", + cur_cpu_spec->firmware_features); } void diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/head.S Thu Jun 19 00:45:34 2003 @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -582,7 +583,7 @@ cmpi 0,r22,0xc /* Segment fault on a bolted segment. Go off and map that segment. */ - beq .do_stab_bolted + beq- .do_stab_bolted stab_bolted_user_return: EXCEPTION_PROLOG_COMMON ld r3,_DSISR(r1) @@ -592,7 +593,7 @@ rlwinm r4,r3,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ ld r3,_DAR(r1) /* into the hash table */ - beq 2f /* If so handle it */ + beq+ 2f /* If so handle it */ li r4,0x300 /* Trap number */ bl .do_stab_SI b 1f @@ -644,7 +645,7 @@ EXCEPTION_PROLOG_COMMON andis. r0,r23,0x0020 /* no ste found? */ - beq 2f + beq+ 2f mr r3,r22 /* SRR0 at interrupt */ li r4,0x400 /* Trap number */ bl .do_stab_SI @@ -674,7 +675,7 @@ li r4,0x480 /* Exception vector */ bl .ste_allocate or. r3,r3,r3 /* Check return code */ - beq fast_exception_return /* Return if we succeeded */ + beq+ fast_exception_return /* Return if we succeeded */ addi r3,r1,STACK_FRAME_OVERHEAD #ifdef DO_SOFT_DISABLE @@ -878,18 +879,8 @@ mfspr r22,DSISR andis. r22,r22,0x0020 - bne+ 2f - ld r22,8(r21) /* get SRR1 */ - andi. r22,r22,MSR_PR /* check if from user */ - bne+ stab_bolted_user_return /* from user, send the error on up */ -#if 0 - li r3,0 -#ifdef CONFIG_XMON - bl .xmon -#endif -1: b 1b -#endif -2: + beq- stab_bolted_user_return + /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ mfspr r21,DAR rldicl r20,r21,36,32 /* Permits a full 32b of ESID */ @@ -1079,9 +1070,11 @@ oris r21,r23,2048 /* valid bit */ rldimi r21,r22,0,52 /* Insert entry */ - isync + /* + * No need for an isync before or after this slbmte. The exception + * we enter with and the rfid we exit with are context synchronizing . + */ slbmte r20,r21 - isync /* All done -- return from exception. */ mfsprg r20,3 /* Load the PACA pointer */ @@ -1248,6 +1241,11 @@ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) + LOADADDR(r3,cpu_specs) + LOADADDR(r4,cur_cpu_spec) + li r5,0 + bl .identify_cpu + LOADADDR(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1691,6 +1689,13 @@ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) + LOADADDR(r3,cpu_specs) + sub r3,r3,r26 + LOADADDR(r4,cur_cpu_spec) + sub r4,r4,r26 + mr r5,r26 + bl .identify_cpu + /* set up the TOC (physical address) */ LOADADDR(r2,__toc_start) addi r2,r2,0x4000 @@ -1814,9 +1819,9 @@ li r5,0 std r0,PACAKSAVE(r13) - /* ptr to hardware interrupt stack for processor 0 */ + /* ptr to hardware interrupt stack for boot processor */ LOADADDR(r3, hardware_int_paca0) - li r5,0x1000 + li r5,PAGE_SIZE sldi r5,r5,3 subi r5,r5,STACK_FRAME_OVERHEAD @@ -1849,6 +1854,11 @@ bl .start_kernel +_GLOBAL(__setup_cpu_power3) + blr +_GLOBAL(__setup_cpu_power4) + blr + _GLOBAL(hmt_init) #ifdef CONFIG_HMT LOADADDR(r5, hmt_thread_data) @@ -1944,7 +1954,7 @@ .globl hardware_int_paca0 hardware_int_paca0: - .space 8*4096 + .space 8*PAGE_SIZE /* 1 page segment table per cpu (max 48) */ .globl stab_array diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c --- a/arch/ppc64/kernel/htab.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/htab.c Thu Jun 19 00:45:34 2003 @@ -46,6 +46,7 @@ #include #include #include +#include /* * Note: pte --> Linux PTE @@ -101,7 +102,7 @@ hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); - if (naca->platform == PLATFORM_PSERIES_LPAR) + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, (unsigned long)__v2a(addr) >> PAGE_SHIFT, 0, mode, 1, large); @@ -140,7 +141,7 @@ htab_data.htab_num_ptegs = pteg_count; htab_data.htab_hash_mask = pteg_count - 1; - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { /* Find storage for the HPT. Must be contiguous in * the absolute address space. */ @@ -165,15 +166,16 @@ mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; /* XXX we currently map kernel text rw, should fix this */ - if (cpu_has_largepage() && naca->physicalMemorySize > 256*MB) { + if ((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + && systemcfg->physicalMemorySize > 256*MB) { create_pte_mapping((unsigned long)KERNELBASE, KERNELBASE + 256*MB, mode_rw, 0); create_pte_mapping((unsigned long)KERNELBASE + 256*MB, - KERNELBASE + (naca->physicalMemorySize), + KERNELBASE + (systemcfg->physicalMemorySize), mode_rw, 1); } else { create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE+(naca->physicalMemorySize), + KERNELBASE+(systemcfg->physicalMemorySize), mode_rw, 0); } } @@ -279,7 +281,8 @@ #define PPC64_HWNOEXEC (1 << 2) /* We do lazy icache flushing on cpus that support it */ - if (unlikely(cpu_has_noexecute() && pfn_valid(pte_pfn(new_pte)))) { + if (unlikely((cur_cpu_spec->cpu_features & CPU_FTR_NOEXECUTE) + && pfn_valid(pte_pfn(new_pte)))) { struct page *page = pte_page(new_pte); /* page is dirty */ diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/iSeries_setup.c Thu Jun 19 00:45:34 2003 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "iSeries_setup.h" @@ -254,7 +255,7 @@ { unsigned long i; unsigned long mem_blocks = 0; - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) mem_blocks = iSeries_process_Regatta_mainstore_vpd( mb_array, max_entries ); else mem_blocks = iSeries_process_Condor_mainstore_vpd( mb_array, max_entries ); @@ -311,7 +312,6 @@ ppc_md.setup_residual = iSeries_setup_residual; ppc_md.get_cpuinfo = iSeries_get_cpuinfo; ppc_md.init_IRQ = iSeries_init_IRQ; - ppc_md.init_ras_IRQ = NULL; ppc_md.get_irq = iSeries_get_irq; ppc_md.init = NULL; @@ -860,7 +860,7 @@ { if ( dprof_buffer ) { unsigned i; - for (i=0; i -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#define INCLUDES +#include "compat_ioctl.c" #include -#include -#include -#include -#include -#include -#include - -#include -/* Ugly hack. */ -#undef __KERNEL__ -#include -#define __KERNEL__ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include #include -#include -/* Aiee. Someone does not find a difference between int and long */ -#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) -#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) -#define EXT2_IOC32_GETVERSION _IOR('v', 1, int) -#define EXT2_IOC32_SETVERSION _IOW('v', 2, int) - -extern asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); - -static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - int err; - unsigned long val; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&val); - set_fs (old_fs); - if (!err && put_user(val, (u32 *)arg)) - return -EFAULT; - return err; -} - -static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - int err; - unsigned long val; - - if (get_user(val, (u32 *)arg)) - return -EFAULT; - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&val); - set_fs (old_fs); - if (!err && put_user(val, (u32 *)arg)) - return -EFAULT; - return err; -} - -static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - /* These are just misnamed, they actually get/put from/to user an int */ - switch (cmd) { - case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break; - case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break; - case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; - case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break; - } - return sys_ioctl(fd, cmd, arg); -} - -struct video_tuner32 { - s32 tuner; - u8 name[32]; - u32 rangelow, rangehigh; - u32 flags; - u16 mode, signal; -}; - -static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up) -{ - int i; - - if (get_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __get_user(kp->name[i], &up->name[i]); - __get_user(kp->rangelow, &up->rangelow); - __get_user(kp->rangehigh, &up->rangehigh); - __get_user(kp->flags, &up->flags); - __get_user(kp->mode, &up->mode); - __get_user(kp->signal, &up->signal); - return 0; -} - -static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up) -{ - int i; - - if (put_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __put_user(kp->name[i], &up->name[i]); - __put_user(kp->rangelow, &up->rangelow); - __put_user(kp->rangehigh, &up->rangehigh); - __put_user(kp->flags, &up->flags); - __put_user(kp->mode, &up->mode); - __put_user(kp->signal, &up->signal); - return 0; -} - -struct video_buffer32 { - /* void * */ u32 base; - s32 height, width, depth, bytesperline; -}; - -static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) -{ - u32 tmp; - - if (get_user(tmp, &up->base)) - return -EFAULT; - kp->base = (void *) ((unsigned long)tmp); - __get_user(kp->height, &up->height); - __get_user(kp->width, &up->width); - __get_user(kp->depth, &up->depth); - __get_user(kp->bytesperline, &up->bytesperline); - return 0; -} - -static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) -{ - u32 tmp = (u32)((unsigned long)kp->base); - - if (put_user(tmp, &up->base)) - return -EFAULT; - __put_user(kp->height, &up->height); - __put_user(kp->width, &up->width); - __put_user(kp->depth, &up->depth); - __put_user(kp->bytesperline, &up->bytesperline); - return 0; -} - -struct video_clip32 { - s32 x, y, width, height; - /* struct video_clip32 * */ u32 next; -}; - -struct video_window32 { - u32 x, y, width, height, chromakey, flags; - /* struct video_clip32 * */ u32 clips; - s32 clipcount; -}; - -static void free_kvideo_clips(struct video_window *kp) -{ - struct video_clip *cp; - - cp = kp->clips; - if (cp != NULL) - kfree(cp); -} - -static int get_video_window32(struct video_window *kp, struct video_window32 *up) -{ - struct video_clip32 *ucp; - struct video_clip *kcp; - int nclips, err, i; - u32 tmp; - - if (get_user(kp->x, &up->x)) - return -EFAULT; - __get_user(kp->y, &up->y); - __get_user(kp->width, &up->width); - __get_user(kp->height, &up->height); - __get_user(kp->chromakey, &up->chromakey); - __get_user(kp->flags, &up->flags); - __get_user(kp->clipcount, &up->clipcount); - __get_user(tmp, &up->clips); - ucp = (struct video_clip32 *)A(tmp); - kp->clips = NULL; - - nclips = kp->clipcount; - if (nclips == 0) - return 0; - - if (ucp == 0) - return -EINVAL; - - /* Peculiar interface... */ - if (nclips < 0) - nclips = VIDEO_CLIPMAP_SIZE; - - kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL); - err = -ENOMEM; - if (kcp == NULL) - goto cleanup_and_err; - - kp->clips = kcp; - for(i = 0; i < nclips; i++) { - __get_user(kcp[i].x, &ucp[i].x); - __get_user(kcp[i].y, &ucp[i].y); - __get_user(kcp[i].width, &ucp[i].width); - __get_user(kcp[i].height, &ucp[i].height); - kcp[nclips].next = NULL; - } - - return 0; - -cleanup_and_err: - free_kvideo_clips(kp); - return err; -} - -/* You get back everything except the clips... */ -static int put_video_window32(struct video_window *kp, struct video_window32 *up) -{ - if (put_user(kp->x, &up->x)) - return -EFAULT; - __put_user(kp->y, &up->y); - __put_user(kp->width, &up->width); - __put_user(kp->height, &up->height); - __put_user(kp->chromakey, &up->chromakey); - __put_user(kp->flags, &up->flags); - __put_user(kp->clipcount, &up->clipcount); - return 0; -} - -#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) -#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) -#define VIDIOCGWIN32 _IOR('v',9, struct video_window32) -#define VIDIOCSWIN32 _IOW('v',10, struct video_window32) -#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32) -#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) -#define VIDIOCGFREQ32 _IOR('v',14, u32) -#define VIDIOCSFREQ32 _IOW('v',15, u32) - -static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - union { - struct video_tuner vt; - struct video_buffer vb; - struct video_window vw; - unsigned long vx; - } karg; - mm_segment_t old_fs = get_fs(); - void *up = (void *)arg; - int err = 0; - - /* First, convert the command. */ - switch(cmd) { - case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; - case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; - case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; - case VIDIOCSWIN32: cmd = VIDIOCSWIN; break; - case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; - case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; - case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; - case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; - }; - - switch(cmd) { - case VIDIOCSTUNER: - case VIDIOCGTUNER: - err = get_video_tuner32(&karg.vt, up); - break; - - case VIDIOCSWIN: - err = get_video_window32(&karg.vw, up); - break; - - case VIDIOCSFBUF: - err = get_video_buffer32(&karg.vb, up); - break; - - case VIDIOCSFREQ: - err = get_user(karg.vx, (u32 *)up); - break; - }; - if (err) - goto out; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&karg); - set_fs(old_fs); - - if (cmd == VIDIOCSWIN) - free_kvideo_clips(&karg.vw); - - if (err == 0) { - switch(cmd) { - case VIDIOCGTUNER: - err = put_video_tuner32(&karg.vt, up); - break; - - case VIDIOCGWIN: - err = put_video_window32(&karg.vw, up); - break; - - case VIDIOCGFBUF: - err = put_video_buffer32(&karg.vb, up); - break; - - case VIDIOCGFREQ: - err = put_user(((u32)karg.vx), (u32 *)up); - break; - }; - } -out: - return err; -} - -static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct compat_timeval *up = (struct compat_timeval *)arg; - struct timeval ktv; - mm_segment_t old_fs = get_fs(); - int err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&ktv); - set_fs(old_fs); - if (!err) { - err = put_user(ktv.tv_sec, &up->tv_sec); - err |= __put_user(ktv.tv_usec, &up->tv_usec); - } - return err; -} - -struct ifmap32 { - u32 mem_start; - u32 mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; -}; - -struct ifreq32 { -#define IFHWADDRLEN 6 -#define IFNAMSIZ 16 - union { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_ivalue; - int ifru_mtu; - struct ifmap32 ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - char ifru_newname[IFNAMSIZ]; - compat_caddr_t ifru_data; - } ifr_ifru; -}; - -struct ifconf32 { - int ifc_len; /* size of buffer */ - compat_caddr_t ifcbuf; -}; - -#ifdef CONFIG_NET -static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct net_device *dev; - struct ifreq32 ifr32; - int err; - - if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - - dev = dev_get_by_index(ifr32.ifr_ifindex); - if (!dev) - return -ENODEV; - - strcpy(ifr32.ifr_name, dev->name); - dev_put(dev); - - err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32)); - return (err ? -EFAULT : 0); -} -#endif - -static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ifconf32 ifc32; - struct ifconf ifc; - struct ifreq32 *ifr32; - struct ifreq *ifr; - mm_segment_t old_fs; - unsigned int i, j; - int err; - - if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32))) - return -EFAULT; - - if (ifc32.ifcbuf == 0) { - ifc32.ifc_len = 0; - ifc.ifc_len = 0; - ifc.ifc_buf = NULL; - } else { - ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * - sizeof (struct ifreq); - ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); - if (!ifc.ifc_buf) - return -ENOMEM; - } - ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); - for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { - if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { - kfree (ifc.ifc_buf); - return -EFAULT; - } - } - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); - set_fs (old_fs); - if (!err) { - ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); - for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; - i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { - if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { - err = -EFAULT; - break; - } - } - if (!err) { - if (ifc32.ifcbuf == 0) { - /* Translate from 64-bit structure multiple to - * a 32-bit one. - */ - i = ifc.ifc_len; - i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32)); - ifc32.ifc_len = i; - } else { - if (i <= ifc32.ifc_len) - ifc32.ifc_len = i; - else - ifc32.ifc_len = i - sizeof (struct ifreq32); - } - if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32))) - err = -EFAULT; - } - } - if (ifc.ifc_buf != NULL) - kfree (ifc.ifc_buf); - return err; -} - -static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ifreq ifr; - mm_segment_t old_fs; - int err, len; - u32 data, ethcmd; - - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL); - if (!ifr.ifr_data) - return -EAGAIN; - - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - - if (get_user(ethcmd, (u32 *)A(data))) { - err = -EFAULT; - goto out; - } - switch (ethcmd) { - case ETHTOOL_GDRVINFO: len = sizeof(struct ethtool_drvinfo); break; - case ETHTOOL_GMSGLVL: - case ETHTOOL_SMSGLVL: - case ETHTOOL_GLINK: - case ETHTOOL_NWAY_RST: len = sizeof(struct ethtool_value); break; - case ETHTOOL_GREGS: { - struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data); - /* darned variable size arguments */ - if (get_user(len, (u32 *)®addr->len)) { - err = -EFAULT; - goto out; - } - len += sizeof(struct ethtool_regs); - break; - } - case ETHTOOL_GSET: - case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break; - default: - err = -EOPNOTSUPP; - goto out; - } - - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { - err = -EFAULT; - goto out; - } - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); - set_fs (old_fs); - if (!err) { - u32 data; - - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - len = copy_to_user((char *)A(data), ifr.ifr_data, len); - if (len) - err = -EFAULT; - } - -out: - free_page((unsigned long)ifr.ifr_data); - return err; -} - -static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg) -{ - struct ifreq ifr; - mm_segment_t old_fs; - int err, len; - u32 data; - - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL); - if (!ifr.ifr_data) - return -EAGAIN; - - switch (cmd) { - case SIOCBONDENSLAVE: - case SIOCBONDRELEASE: - case SIOCBONDSETHWADDR: - case SIOCBONDCHANGEACTIVE: - len = IFNAMSIZ * sizeof(char); - break; - case SIOCBONDSLAVEINFOQUERY: - len = sizeof(struct ifslave); - break; - case SIOCBONDINFOQUERY: - len = sizeof(struct ifbond); - break; - default: - err = -EINVAL; - goto out; - }; - - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { - err = -EFAULT; - goto out; - } - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); - set_fs (old_fs); - if (!err) { - len = copy_to_user((char *)A(data), ifr.ifr_data, len); - if (len) - err = -EFAULT; - } - -out: - free_page((unsigned long)ifr.ifr_data); - return err; -} - -static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ifreq ifr; - mm_segment_t old_fs; - int err; - - switch (cmd) { - case SIOCSIFMAP: - err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name)); - err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); - err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); - err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); - err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); - err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); - err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); - if (err) - return -EFAULT; - break; - default: - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - break; - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); - set_fs (old_fs); - if (!err) { - switch (cmd) { - case SIOCGIFFLAGS: - case SIOCGIFMETRIC: - case SIOCGIFMTU: - case SIOCGIFMEM: - case SIOCGIFHWADDR: - case SIOCGIFINDEX: - case SIOCGIFADDR: - case SIOCGIFBRDADDR: - case SIOCGIFDSTADDR: - case SIOCGIFNETMASK: - case SIOCGIFTXQLEN: - if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32))) - return -EFAULT; - break; - case SIOCGIFMAP: - err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name)); - err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); - err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); - err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); - err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); - err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); - err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); - if (err) - err = -EFAULT; - break; - } - } - return err; -} - -struct rtentry32 { - u32 rt_pad1; - struct sockaddr rt_dst; /* target address */ - struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ - struct sockaddr rt_genmask; /* target network mask (IP) */ - unsigned short rt_flags; - short rt_pad2; - u32 rt_pad3; - unsigned char rt_tos; - unsigned char rt_class; - short rt_pad4; - short rt_metric; /* +1 for binary compatibility! */ - /* char * */ u32 rt_dev; /* forcing the device at add */ - u32 rt_mtu; /* per route MTU/Window */ - u32 rt_window; /* Window clamping */ - unsigned short rt_irtt; /* Initial RTT */ - -}; - -struct in6_rtmsg32 { - struct in6_addr rtmsg_dst; - struct in6_addr rtmsg_src; - struct in6_addr rtmsg_gateway; - u32 rtmsg_type; - u16 rtmsg_dst_len; - u16 rtmsg_src_len; - u32 rtmsg_metric; - u32 rtmsg_info; - u32 rtmsg_flags; - s32 rtmsg_ifindex; -}; - -static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int ret; - void *r = NULL; - struct in6_rtmsg r6; - struct rtentry r4; - char devname[16]; - u32 rtdev; - mm_segment_t old_fs = get_fs(); - - struct socket *mysock = sockfd_lookup(fd, &ret); - - if (mysock && mysock->sk && mysock->sk->family == AF_INET6) { /* ipv6 */ - ret = copy_from_user (&r6.rtmsg_dst, &(((struct in6_rtmsg32 *)arg)->rtmsg_dst), - 3 * sizeof(struct in6_addr)); - ret |= __get_user (r6.rtmsg_type, &(((struct in6_rtmsg32 *)arg)->rtmsg_type)); - ret |= __get_user (r6.rtmsg_dst_len, &(((struct in6_rtmsg32 *)arg)->rtmsg_dst_len)); - ret |= __get_user (r6.rtmsg_src_len, &(((struct in6_rtmsg32 *)arg)->rtmsg_src_len)); - ret |= __get_user (r6.rtmsg_metric, &(((struct in6_rtmsg32 *)arg)->rtmsg_metric)); - ret |= __get_user (r6.rtmsg_info, &(((struct in6_rtmsg32 *)arg)->rtmsg_info)); - ret |= __get_user (r6.rtmsg_flags, &(((struct in6_rtmsg32 *)arg)->rtmsg_flags)); - ret |= __get_user (r6.rtmsg_ifindex, &(((struct in6_rtmsg32 *)arg)->rtmsg_ifindex)); - - r = (void *) &r6; - } else { /* ipv4 */ - ret = copy_from_user (&r4.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr)); - ret |= __get_user (r4.rt_flags, &(((struct rtentry32 *)arg)->rt_flags)); - ret |= __get_user (r4.rt_metric, &(((struct rtentry32 *)arg)->rt_metric)); - ret |= __get_user (r4.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu)); - ret |= __get_user (r4.rt_window, &(((struct rtentry32 *)arg)->rt_window)); - ret |= __get_user (r4.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt)); - ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev)); - if (rtdev) { - ret |= copy_from_user (devname, (char *)A(rtdev), 15); - r4.rt_dev = devname; devname[15] = 0; - } else - r4.rt_dev = 0; - - r = (void *) &r4; - } - - if (ret) - return -EFAULT; - - set_fs (KERNEL_DS); - ret = sys_ioctl (fd, cmd, (long) r); - set_fs (old_fs); - - if (mysock) - sockfd_put(mysock); - - return ret; -} - -struct hd_geometry32 { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - u32 start; -}; - -static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct hd_geometry geo; - int err; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); - set_fs (old_fs); - if (!err) { - if (copy_to_user ((struct hd_geometry32 *)arg, &geo, 4) || - __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start))) - err = -EFAULT; - } - return err; -} +#define CODE +#include "compat_ioctl.c" struct hd_big_geometry32 { unsigned char heads; @@ -856,1210 +56,6 @@ return err; } -static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - unsigned long kval; - unsigned int *uvp; - int error; - - set_fs(KERNEL_DS); - error = sys_ioctl(fd, cmd, (long)&kval); - set_fs(old_fs); - - if (error == 0) { - uvp = (unsigned int *)arg; - if (put_user(kval, uvp)) - error = -EFAULT; - } - return error; -} - -struct floppy_struct32 { - unsigned int size; - unsigned int sect; - unsigned int head; - unsigned int track; - unsigned int stretch; - unsigned char gap; - unsigned char rate; - unsigned char spec1; - unsigned char fmt_gap; - const compat_caddr_t name; -}; - -struct floppy_drive_params32 { - char cmos; - u32 max_dtr; - u32 hlt; - u32 hut; - u32 srt; - u32 spinup; - u32 spindown; - unsigned char spindown_offset; - unsigned char select_delay; - unsigned char rps; - unsigned char tracks; - u32 timeout; - unsigned char interleave_sect; - struct floppy_max_errors max_errors; - char flags; - char read_track; - short autodetect[8]; - int checkfreq; - int native_format; -}; - -struct floppy_drive_struct32 { - signed char flags; - u32 spinup_date; - u32 select_date; - u32 first_read_date; - short probed_format; - short track; - short maxblock; - short maxtrack; - int generation; - int keep_data; - int fd_ref; - int fd_device; - int last_checked; - compat_caddr_t dmabuf; - int bufblocks; -}; - -struct floppy_fdc_state32 { - int spec1; - int spec2; - int dtr; - unsigned char version; - unsigned char dor; - u32 address; - unsigned int rawcmd:2; - unsigned int reset:1; - unsigned int need_configure:1; - unsigned int perp_mode:2; - unsigned int has_fifo:1; - unsigned int driver_version; - unsigned char track[4]; -}; - -struct floppy_write_errors32 { - unsigned int write_errors; - u32 first_error_sector; - int first_error_generation; - u32 last_error_sector; - int last_error_generation; - unsigned int badness; -}; - -#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) -#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32) -#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32) -#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32) -#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32) -#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32) -#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32) -#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32) -#define FDWERRORGET32 _IOR(2, 0x17, struct floppy_write_errors32) - -static struct { - unsigned int cmd32; - unsigned int cmd; -} fd_ioctl_trans_table[] = { - { FDSETPRM32, FDSETPRM }, - { FDDEFPRM32, FDDEFPRM }, - { FDGETPRM32, FDGETPRM }, - { FDSETDRVPRM32, FDSETDRVPRM }, - { FDGETDRVPRM32, FDGETDRVPRM }, - { FDGETDRVSTAT32, FDGETDRVSTAT }, - { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, - { FDGETFDCSTAT32, FDGETFDCSTAT }, - { FDWERRORGET32, FDWERRORGET } -}; - -#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0])) - -static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - void *karg = NULL; - unsigned int kcmd = 0; - int i, err; - - for (i = 0; i < NR_FD_IOCTL_TRANS; i++) - if (cmd == fd_ioctl_trans_table[i].cmd32) { - kcmd = fd_ioctl_trans_table[i].cmd; - break; - } - if (!kcmd) - return -EINVAL; - - switch (cmd) { - case FDSETPRM32: - case FDDEFPRM32: - case FDGETPRM32: - { - struct floppy_struct *f; - - f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETPRM32) - break; - err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size); - err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect); - err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head); - err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track); - err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); - err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap); - err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate); - err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); - err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); - err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDSETDRVPRM32: - case FDGETDRVPRM32: - { - struct floppy_drive_params *f; - - f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETDRVPRM32) - break; - err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); - err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); - err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); - err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); - err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); - err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); - err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); - err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); - err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); - err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); - err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); - err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); - err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); - err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors)); - err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); - err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); - err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect)); - err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); - err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDGETFDCSTAT32: - karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDWERRORGET32: - karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - default: - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case FDGETPRM32: - { - struct floppy_struct *f = karg; - - err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size); - err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect); - err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head); - err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track); - err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); - err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap); - err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate); - err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); - err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); - err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); - break; - } - case FDGETDRVPRM32: - { - struct floppy_drive_params *f = karg; - - err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); - err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); - err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); - err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); - err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); - err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); - err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); - err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); - err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); - err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); - err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); - err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); - err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); - err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors)); - err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); - err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); - err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect)); - err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); - err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - { - struct floppy_drive_struct *f = karg; - - err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags); - err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date); - err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date); - err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date); - err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format); - err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track); - err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock); - err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack); - err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation); - err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data); - err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref); - err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device); - err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked); - err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf); - err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks); - break; - } - case FDGETFDCSTAT32: - { - struct floppy_fdc_state *f = karg; - - err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1); - err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2); - err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr); - err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version); - err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor); - err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address); - err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address - + sizeof(((struct floppy_fdc_state32 *)arg)->address), - (char *)&f->address + sizeof(f->address), sizeof(int)); - err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version); - err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track)); - break; - } - case FDWERRORGET32: - { - struct floppy_write_errors *f = karg; - - err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors); - err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector); - err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation); - err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector); - err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation); - err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness); - break; - } - default: - break; - } - if (err) - err = -EFAULT; - -out: if (karg) kfree(karg); - return err; -} - -typedef struct sg_io_hdr32 { - s32 interface_id; /* [i] 'S' for SCSI generic (required) */ - s32 dxfer_direction; /* [i] data transfer direction */ - u8 cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ - u8 mx_sb_len; /* [i] max length to write to sbp */ - u16 iovec_count; /* [i] 0 implies no scatter gather */ - u32 dxfer_len; /* [i] byte count of data transfer */ - u32 dxferp; /* [i], [*io] points to data transfer memory - or scatter gather list */ - u32 cmdp; /* [i], [*i] points to command to perform */ - u32 sbp; /* [i], [*o] points to sense_buffer memory */ - u32 timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ - u32 flags; /* [i] 0 -> default, see SG_FLAG... */ - s32 pack_id; /* [i->o] unused internally (normally) */ - u32 usr_ptr; /* [i->o] unused internally */ - u8 status; /* [o] scsi status */ - u8 masked_status; /* [o] shifted, masked scsi status */ - u8 msg_status; /* [o] messaging level data (optional) */ - u8 sb_len_wr; /* [o] byte count actually written to sbp */ - u16 host_status; /* [o] errors from host adapter */ - u16 driver_status; /* [o] errors from software driver */ - s32 resid; /* [o] dxfer_len - actual_transferred */ - u32 duration; /* [o] time taken by cmd (unit: millisec) */ - u32 info; /* [o] auxiliary information */ -} sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ - -typedef struct sg_iovec32 { - u32 iov_base; - u32 iov_len; -} sg_iovec32_t; - -static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) -{ - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); - sg_iovec_t *kiov; - int i; - - sgp->dxferp = kmalloc(sgp->iovec_count * - sizeof(sg_iovec_t), GFP_KERNEL); - if (!sgp->dxferp) - return -ENOMEM; - memset(sgp->dxferp, 0, - sgp->iovec_count * sizeof(sg_iovec_t)); - - kiov = (sg_iovec_t *) sgp->dxferp; - for (i = 0; i < sgp->iovec_count; i++) { - u32 iov_base32; - if (__get_user(iov_base32, &uiov->iov_base) || - __get_user(kiov->iov_len, &uiov->iov_len)) - return -EFAULT; - - kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); - if (!kiov->iov_base) - return -ENOMEM; - if (copy_from_user(kiov->iov_base, - (void *) A(iov_base32), - kiov->iov_len)) - return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) -{ - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - u32 iov_base32; - - if (__get_user(iov_base32, &uiov->iov_base)) - return -EFAULT; - - if (copy_to_user((void *) A(iov_base32), - kiov->iov_base, - kiov->iov_len)) - return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static void free_sg_iovec(sg_io_hdr_t *sgp) -{ - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - if (kiov->iov_base) { - kfree(kiov->iov_base); - kiov->iov_base = NULL; - } - kiov++; - } - kfree(sgp->dxferp); - sgp->dxferp = NULL; -} - -static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - sg_io_hdr32_t *sg_io32; - sg_io_hdr_t sg_io64; - u32 dxferp32, cmdp32, sbp32; - mm_segment_t old_fs; - int err = 0; - - sg_io32 = (sg_io_hdr32_t *)arg; - err = __get_user(sg_io64.interface_id, &sg_io32->interface_id); - err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction); - err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len); - err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len); - err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count); - err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len); - err |= __get_user(sg_io64.timeout, &sg_io32->timeout); - err |= __get_user(sg_io64.flags, &sg_io32->flags); - err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id); - - sg_io64.dxferp = NULL; - sg_io64.cmdp = NULL; - sg_io64.sbp = NULL; - - err |= __get_user(cmdp32, &sg_io32->cmdp); - sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); - if (!sg_io64.cmdp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.cmdp, - (void *) A(cmdp32), - sg_io64.cmd_len)) { - err = -EFAULT; - goto out; - } - - err |= __get_user(sbp32, &sg_io32->sbp); - sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL); - if (!sg_io64.sbp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.sbp, - (void *) A(sbp32), - sg_io64.mx_sb_len)) { - err = -EFAULT; - goto out; - } - - err |= __get_user(dxferp32, &sg_io32->dxferp); - if (sg_io64.iovec_count) { - int ret; - - if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) { - err = ret; - goto out; - } - } else { - sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); - if (!sg_io64.dxferp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.dxferp, - (void *) A(dxferp32), - sg_io64.dxfer_len)) { - err = -EFAULT; - goto out; - } - } - - /* Unused internally, do not even bother to copy it over. */ - sg_io64.usr_ptr = NULL; - - if (err) - return -EFAULT; - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64); - set_fs (old_fs); - - if (err < 0) - goto out; - - err = __put_user(sg_io64.pack_id, &sg_io32->pack_id); - err |= __put_user(sg_io64.status, &sg_io32->status); - err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status); - err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status); - err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr); - err |= __put_user(sg_io64.host_status, &sg_io32->host_status); - err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status); - err |= __put_user(sg_io64.resid, &sg_io32->resid); - err |= __put_user(sg_io64.duration, &sg_io32->duration); - err |= __put_user(sg_io64.info, &sg_io32->info); - err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) - err |= copy_back_sg_iovec(&sg_io64, dxferp32); - else - err |= copy_to_user((void *)A(dxferp32), - sg_io64.dxferp, - sg_io64.dxfer_len); - } - if (err) - err = -EFAULT; - -out: - if (sg_io64.cmdp) - kfree(sg_io64.cmdp); - if (sg_io64.sbp) - kfree(sg_io64.sbp); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) { - free_sg_iovec(&sg_io64); - } else { - kfree(sg_io64.dxferp); - } - } - return err; -} - -struct ppp_option_data32 { - compat_caddr_t ptr; - __u32 length; - int transmit; -}; -#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) - -struct ppp_idle32 { - compat_time_t xmit_idle; - compat_time_t recv_idle; -}; -#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) - -static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct ppp_option_data32 data32; - struct ppp_option_data data; - struct ppp_idle32 idle32; - struct ppp_idle idle; - unsigned int kcmd; - void *karg; - int err = 0; - - switch (cmd) { - case PPPIOCGIDLE32: - kcmd = PPPIOCGIDLE; - karg = &idle; - break; - case PPPIOCSCOMPRESS32: - if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32))) - return -EFAULT; - data.ptr = kmalloc (data32.length, GFP_KERNEL); - if (!data.ptr) - return -ENOMEM; - if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) { - kfree(data.ptr); - return -EFAULT; - } - data.length = data32.length; - data.transmit = data32.transmit; - kcmd = PPPIOCSCOMPRESS; - karg = &data; - break; - default: - do { - static int count = 0; - if (++count <= 20) - printk("ppp_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while (0); - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - switch (cmd) { - case PPPIOCGIDLE32: - if (err) - return err; - idle32.xmit_idle = idle.xmit_idle; - idle32.recv_idle = idle.recv_idle; - if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32))) - return -EFAULT; - break; - case PPPIOCSCOMPRESS32: - kfree(data.ptr); - break; - default: - break; - } - return err; -} - - -struct mtget32 { - __u32 mt_type; - __u32 mt_resid; - __u32 mt_dsreg; - __u32 mt_gstat; - __u32 mt_erreg; - compat_daddr_t mt_fileno; - compat_daddr_t mt_blkno; -}; -#define MTIOCGET32 _IOR('m', 2, struct mtget32) - -struct mtpos32 { - __u32 mt_blkno; -}; -#define MTIOCPOS32 _IOR('m', 3, struct mtpos32) - -struct mtconfiginfo32 { - __u32 mt_type; - __u32 ifc_type; - __u16 irqnr; - __u16 dmanr; - __u16 port; - __u32 debug; - __u32 have_dens:1; - __u32 have_bsf:1; - __u32 have_fsr:1; - __u32 have_bsr:1; - __u32 have_eod:1; - __u32 have_seek:1; - __u32 have_tell:1; - __u32 have_ras1:1; - __u32 have_ras2:1; - __u32 have_ras3:1; - __u32 have_qfa:1; - __u32 pad1:5; - char reserved[10]; -}; -#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) -#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32) - -static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct mtconfiginfo info; - struct mtget get; - struct mtpos pos; - unsigned long kcmd; - void *karg; - int err = 0; - - switch(cmd) { - case MTIOCPOS32: - kcmd = MTIOCPOS; - karg = &pos; - break; - case MTIOCGET32: - kcmd = MTIOCGET; - karg = &get; - break; - case MTIOCGETCONFIG32: - kcmd = MTIOCGETCONFIG; - karg = &info; - break; - case MTIOCSETCONFIG32: - kcmd = MTIOCSETCONFIG; - karg = &info; - err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); - err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); - err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); - err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); - err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port); - err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); - err |= __copy_from_user((char *)&info.debug + sizeof(info.debug), - (char *)&((struct mtconfiginfo32 *)arg)->debug - + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32)); - if (err) - return -EFAULT; - break; - default: - do { - static int count = 0; - if (++count <= 20) - printk("mt_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while (0); - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - return err; - switch (cmd) { - case MTIOCPOS32: - err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno); - break; - case MTIOCGET32: - err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type); - err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid); - err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg); - err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat); - err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg); - err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno); - err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno); - break; - case MTIOCGETCONFIG32: - err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); - err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); - err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); - err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); - err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port); - err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); - err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug - + sizeof(((struct mtconfiginfo32 *)arg)->debug), - (char *)&info.debug + sizeof(info.debug), sizeof(__u32)); - break; - case MTIOCSETCONFIG32: - break; - } - return err ? -EFAULT: 0; -} - -struct cdrom_read32 { - int cdread_lba; - compat_caddr_t cdread_bufaddr; - int cdread_buflen; -}; - -struct cdrom_read_audio32 { - union cdrom_addr addr; - u_char addr_format; - int nframes; - compat_caddr_t buf; -}; - -struct cdrom_generic_command32 { - unsigned char cmd[CDROM_PACKET_SIZE]; - compat_caddr_t buffer; - unsigned int buflen; - int stat; - compat_caddr_t sense; - compat_caddr_t reserved[3]; -}; - -static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct cdrom_read cdread; - struct cdrom_read_audio cdreadaudio; - struct cdrom_generic_command cgc; - compat_caddr_t addr; - char *data = 0; - void *karg; - int err = 0; - - switch(cmd) { - case CDROMREADMODE2: - case CDROMREADMODE1: - case CDROMREADRAW: - case CDROMREADCOOKED: - karg = &cdread; - err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba); - err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr); - err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen); - if (err) - return -EFAULT; - data = kmalloc(cdread.cdread_buflen, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdread.cdread_bufaddr = data; - break; - case CDROMREADAUDIO: - karg = &cdreadaudio; - err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr)); - err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format); - err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); - err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf); - if (err) - return -EFAULT; - data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdreadaudio.buf = data; - break; - case CDROM_SEND_PACKET: - karg = &cgc; - err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd)); - err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer); - err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen); - if (err) - return -EFAULT; - if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL) - return -ENOMEM; - cgc.buffer = data; - break; - default: - do { - static int count = 0; - if (++count <= 20) - printk("cdrom_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while (0); - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case CDROMREADMODE2: - case CDROMREADMODE1: - case CDROMREADRAW: - case CDROMREADCOOKED: - err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen); - break; - case CDROMREADAUDIO: - err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352); - break; - case CDROM_SEND_PACKET: - err = copy_to_user((char *)A(addr), data, cgc.buflen); - break; - default: - break; - } -out: if (data) - kfree(data); - return err ? -EFAULT : 0; -} - -struct loop_info32 { - int lo_number; /* ioctl r/o */ - compat_dev_t lo_device; /* ioctl r/o */ - unsigned int lo_inode; /* ioctl r/o */ - compat_dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ - char lo_name[LO_NAME_SIZE]; - unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned int lo_init[2]; - char reserved[4]; -}; - -static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct loop_info l; - int err = -EINVAL; - - switch(cmd) { - case LOOP_SET_STATUS: - err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); - err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); - err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); - err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); - err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset, - 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); - if (err) { - err = -EFAULT; - } else { - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&l); - set_fs (old_fs); - } - break; - case LOOP_GET_STATUS: - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&l); - set_fs (old_fs); - if (!err) { - err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); - err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); - err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); - err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); - err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset, - (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); - if (err) - err = -EFAULT; - } - break; - default: { - static int count = 0; - if (++count <= 20) - printk("%s: Unknown loop ioctl cmd, fd(%d) " - "cmd(%08x) arg(%08lx)\n", - __FUNCTION__, fd, cmd, arg); - } - } - return err; -} - -extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); - -#ifdef CONFIG_VT -static int vt_check(struct file *file) -{ - struct tty_struct *tty; - struct inode *inode = file->f_dentry->d_inode; - - if (file->f_op->ioctl != tty_ioctl) - return -EINVAL; - - tty = (struct tty_struct *)file->private_data; - if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl")) - return -EINVAL; - - if (tty->driver->ioctl != vt_ioctl) - return -EINVAL; - - /* - * To have permissions to do most of the vt ioctls, we either have - * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. - */ - if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) - return 1; - return 0; -} - -struct consolefontdesc32 { - unsigned short charcount; /* characters in font (256 or 512) */ - unsigned short charheight; /* scan lines per character (1-32) */ - u32 chardata; /* font data in expanded form */ -}; - -static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file) -{ - struct consolefontdesc cfdarg; - struct console_font_op op; - int i, perm; - - perm = vt_check(file); - if (perm < 0) return perm; - - if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32))) - return -EFAULT; - - cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata); - - switch (cmd) { - case PIO_FONTX: - if (!perm) - return -EPERM; - op.op = KD_FONT_OP_SET; - op.flags = 0; - op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - return con_font_op(fg_console, &op); - case GIO_FONTX: - if (!cfdarg.chardata) - return 0; - op.op = KD_FONT_OP_GET; - op.flags = 0; - op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - i = con_font_op(fg_console, &op); - if (i) - return i; - cfdarg.charheight = op.height; - cfdarg.charcount = op.charcount; - ((struct consolefontdesc32 *)&cfdarg)->chardata = (unsigned long)cfdarg.chardata; - if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32))) - return -EFAULT; - return 0; - } - return -EINVAL; -} - -struct console_font_op32 { - unsigned int op; /* operation code KD_FONT_OP_* */ - unsigned int flags; /* KD_FONT_FLAG_* */ - unsigned int width, height; /* font size */ - unsigned int charcount; - u32 data; /* font data with height fixed to 32 */ -}; - -static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file) -{ - struct console_font_op op; - int perm = vt_check(file), i; - struct vt_struct *vt; - - if (perm < 0) return perm; - - if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32))) - return -EFAULT; - if (!perm && op.op != KD_FONT_OP_GET) - return -EPERM; - op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data); - op.flags |= KD_FONT_FLAG_OLD; - vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data; - i = con_font_op(vt->vc_num, &op); - if (i) return i; - ((struct console_font_op32 *)&op)->data = (unsigned long)op.data; - if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32))) - return -EFAULT; - return 0; -} - -struct fb_fix_screeninfo32 { - char id[16]; /* identification string eg "TT Builtin" */ - unsigned int smem_start; /* Start of frame buffer mem */ - /* (physical address) */ - __u32 smem_len; /* Length of frame buffer mem */ - __u32 type; /* see FB_TYPE_* */ - __u32 type_aux; /* Interleave for interleaved Planes */ - __u32 visual; /* see FB_VISUAL_* */ - __u16 xpanstep; /* zero if no hardware panning */ - __u16 ypanstep; /* zero if no hardware panning */ - __u16 ywrapstep; /* zero if no hardware ywrap */ - __u32 line_length; /* length of a line in bytes */ - unsigned int mmio_start; /* Start of Memory Mapped I/O */ - /* (physical address) */ - __u32 mmio_len; /* Length of Memory Mapped I/O */ - __u32 accel; /* Type of acceleration available */ - __u16 reserved[3]; /* Reserved for future compatibility */ -}; - -static int do_fbioget_fscreeninfo_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct fb_fix_screeninfo fix; - int err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (long)&fix); - set_fs(old_fs); - - if (err == 0) { - unsigned int smem_start = fix.smem_start; /* lose top 32 bits */ - unsigned int mmio_start = fix.mmio_start; /* lose top 32 bits */ - int i; - - err = put_user(fix.id[0], &((struct fb_fix_screeninfo32 *)arg)->id[0]); - for (i=1; i<16; i++) { - err |= __put_user(fix.id[i], &((struct fb_fix_screeninfo32 *)arg)->id[i]); - } - err |= __put_user(smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start); - err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len); - err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type); - err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux); - err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual); - err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep); - err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep); - err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep); - err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length); - err |= __put_user(mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start); - err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len); - err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel); - err |= __put_user(fix.reserved[0], &((struct fb_fix_screeninfo32 *)arg)->reserved[0]); - err |= __put_user(fix.reserved[1], &((struct fb_fix_screeninfo32 *)arg)->reserved[1]); - err |= __put_user(fix.reserved[2], &((struct fb_fix_screeninfo32 *)arg)->reserved[2]); - if (err) - err = -EFAULT; - } - return err; -} - -struct fb_cmap32 { - __u32 start; /* First entry */ - __u32 len; /* Number of entries */ - __u32 redptr; /* Red values */ - __u32 greenptr; - __u32 blueptr; - __u32 transpptr; /* transparency, can be NULL */ -}; - -static int do_fbiogetcmap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct fb_cmap cmap; - int err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (long)&cmap); - set_fs(old_fs); - - if (err == 0) { - __u32 redptr = (__u32)(__u64)cmap.red; - __u32 greenptr = (__u32)(__u64)cmap.green; - __u32 blueptr = (__u32)(__u64)cmap.blue; - __u32 transpptr = (__u32)(__u64)cmap.transp; - - err = put_user(cmap.start, &((struct fb_cmap32 *)arg)->start); - err |= __put_user(cmap.len, &((struct fb_cmap32 *)arg)->len); - err |= __put_user(redptr, &((struct fb_cmap32 *)arg)->redptr); - err |= __put_user(greenptr, &((struct fb_cmap32 *)arg)->greenptr); - err |= __put_user(blueptr, &((struct fb_cmap32 *)arg)->blueptr); - err |= __put_user(transpptr, &((struct fb_cmap32 *)arg)->transpptr); - if (err) - err = -EFAULT; - } - return err; -} - -static int do_fbioputcmap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct fb_cmap cmap; - __u32 redptr, greenptr, blueptr, transpptr; - int err; - - err = get_user(cmap.start, &((struct fb_cmap32 *)arg)->start); - err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len); - err |= __get_user(redptr, &((struct fb_cmap32 *)arg)->redptr); - err |= __get_user(greenptr, &((struct fb_cmap32 *)arg)->greenptr); - err |= __get_user(blueptr, &((struct fb_cmap32 *)arg)->blueptr); - err |= __get_user(transpptr, &((struct fb_cmap32 *)arg)->transpptr); - - if (err) { - err = -EFAULT; - } else { - cmap.red = (__u16 *)(__u64)redptr; - cmap.green = (__u16 *)(__u64)greenptr; - cmap.blue = (__u16 *)(__u64)blueptr; - cmap.transp = (__u16 *)(__u64)transpptr; - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&cmap); - set_fs (old_fs); - } - return err; -} - -struct unimapdesc32 { - unsigned short entry_ct; - u32 entries; -}; - -static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file) -{ - struct unimapdesc32 tmp; - int perm = vt_check(file); - - if (perm < 0) return perm; - if (copy_from_user(&tmp, user_ud, sizeof tmp)) - return -EFAULT; - switch (cmd) { - case PIO_UNIMAP: - if (!perm) return -EPERM; - return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries)); - case GIO_UNIMAP: - return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries)); - } - return 0; -} -#endif /* CONFIG_VT */ -static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - __kernel_uid_t kuid; - int err; - - cmd = SMB_IOC_GETMOUNTUID; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&kuid); - set_fs(old_fs); - - if (err >= 0) - err = put_user(kuid, (compat_uid_t *)arg); - - return err; -} - struct ncp_ioctl_request_32 { unsigned int function; unsigned int size; @@ -2360,812 +356,6 @@ return err; } -struct atmif_sioc32 { - int number; - int length; - compat_caddr_t arg; -}; - -struct atm_iobuf32 { - int length; - compat_caddr_t buffer; -}; - -#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32) -#define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32) -#define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32) -#define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32) -#define ATM_GETADDR32 _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32) -#define ATM_RSTADDR32 _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32) -#define ATM_ADDADDR32 _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32) -#define ATM_DELADDR32 _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32) -#define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32) -#define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32) -#define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32) -#define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32) -#define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32) -#define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32) -#define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32) -#define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32) -#define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32) - -static struct { - unsigned int cmd32; - unsigned int cmd; -} atm_ioctl_map[] = { - { ATM_GETLINKRATE32, ATM_GETLINKRATE }, - { ATM_GETNAMES32, ATM_GETNAMES }, - { ATM_GETTYPE32, ATM_GETTYPE }, - { ATM_GETESI32, ATM_GETESI }, - { ATM_GETADDR32, ATM_GETADDR }, - { ATM_RSTADDR32, ATM_RSTADDR }, - { ATM_ADDADDR32, ATM_ADDADDR }, - { ATM_DELADDR32, ATM_DELADDR }, - { ATM_GETCIRANGE32, ATM_GETCIRANGE }, - { ATM_SETCIRANGE32, ATM_SETCIRANGE }, - { ATM_SETESI32, ATM_SETESI }, - { ATM_SETESIF32, ATM_SETESIF }, - { ATM_GETSTAT32, ATM_GETSTAT }, - { ATM_GETSTATZ32, ATM_GETSTATZ }, - { ATM_GETLOOP32, ATM_GETLOOP }, - { ATM_SETLOOP32, ATM_SETLOOP }, - { ATM_QUERYLOOP32, ATM_QUERYLOOP } -}; - -#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0])) - - -static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct atm_iobuf32 iobuf32; - struct atm_iobuf iobuf = { 0, NULL }; - mm_segment_t old_fs; - int err; - - err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg, - sizeof(struct atm_iobuf32)); - if (err) - return -EFAULT; - - iobuf.length = iobuf32.length; - - if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) { - iobuf.buffer = (void*)(unsigned long)iobuf32.buffer; - } else { - iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL); - if (iobuf.buffer == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(iobuf.buffer, (void *)A(iobuf32.buffer), iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&iobuf); - set_fs (old_fs); - if (err) - goto out; - - if (iobuf.buffer && iobuf.length > 0) { - err = copy_to_user((void *)A(iobuf32.buffer), iobuf.buffer, iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } - } - err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length)); - - out: - if (iobuf32.buffer && iobuf32.length > 0) - kfree(iobuf.buffer); - - return err; -} - - -static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct atmif_sioc32 sioc32; - struct atmif_sioc sioc = { 0, 0, NULL }; - mm_segment_t old_fs; - int err; - - err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg, - sizeof(struct atmif_sioc32)); - if (err) - return -EFAULT; - - sioc.number = sioc32.number; - sioc.length = sioc32.length; - - if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) { - sioc.arg = (void*)(unsigned long)sioc32.arg; - } else { - sioc.arg = kmalloc(sioc.length, GFP_KERNEL); - if (sioc.arg == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(sioc.arg, (void *)A(sioc32.arg), sioc32.length); - if (err) { - err = -EFAULT; - goto out; - } - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&sioc); - set_fs (old_fs); - if (err) { - goto out; - } - - if (sioc.arg && sioc.length > 0) { - err = copy_to_user((void *)A(sioc32.arg), sioc.arg, sioc.length); - if (err) { - err = -EFAULT; - goto out; - } - } - err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length)); - - out: - if (sioc32.arg && sioc32.length > 0) - kfree(sioc.arg); - - return err; -} - - -static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) -{ - int i; - unsigned int cmd = 0; - - switch (cmd32) { - case SONET_GETSTAT: - case SONET_GETSTATZ: - case SONET_GETDIAG: - case SONET_SETDIAG: - case SONET_CLRDIAG: - case SONET_SETFRAMING: - case SONET_GETFRAMING: - case SONET_GETFRSENSE: - return do_atmif_sioc(fd, cmd32, arg); - } - - for (i = 0; i < NR_ATM_IOCTL; i++) { - if (cmd32 == atm_ioctl_map[i].cmd32) { - cmd = atm_ioctl_map[i].cmd; - break; - } - } - if (i == NR_ATM_IOCTL) { - return -EINVAL; - } - - switch (cmd) { - case ATM_GETNAMES: - return do_atm_iobuf(fd, cmd, arg); - - case ATM_GETLINKRATE: - case ATM_GETTYPE: - case ATM_GETESI: - case ATM_GETADDR: - case ATM_RSTADDR: - case ATM_ADDADDR: - case ATM_DELADDR: - case ATM_GETCIRANGE: - case ATM_SETCIRANGE: - case ATM_SETESI: - case ATM_SETESIF: - case ATM_GETSTAT: - case ATM_GETSTATZ: - case ATM_GETLOOP: - case ATM_SETLOOP: - case ATM_QUERYLOOP: - return do_atmif_sioc(fd, cmd, arg); - } - - return -EINVAL; -} - -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -/* This really belongs in include/linux/drm.h -DaveM */ -#include "../../../drivers/char/drm/drm.h" - -typedef struct drm32_version { - int version_major; /* Major version */ - int version_minor; /* Minor version */ - int version_patchlevel;/* Patch level */ - int name_len; /* Length of name buffer */ - u32 name; /* Name of driver */ - int date_len; /* Length of date buffer */ - u32 date; /* User-space buffer to hold date */ - int desc_len; /* Length of desc buffer */ - u32 desc; /* User-space buffer to hold desc */ -} drm32_version_t; -#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t) - -static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_version_t *uversion = (drm32_version_t *)arg; - char *name_ptr, *date_ptr, *desc_ptr; - u32 tmp1, tmp2, tmp3; - drm_version_t kversion; - mm_segment_t old_fs; - int ret; - - memset(&kversion, 0, sizeof(kversion)); - if (get_user(kversion.name_len, &uversion->name_len) || - get_user(kversion.date_len, &uversion->date_len) || - get_user(kversion.desc_len, &uversion->desc_len) || - get_user(tmp1, &uversion->name) || - get_user(tmp2, &uversion->date) || - get_user(tmp3, &uversion->desc)) - return -EFAULT; - - name_ptr = (char *) A(tmp1); - date_ptr = (char *) A(tmp2); - desc_ptr = (char *) A(tmp3); - - ret = -ENOMEM; - if (kversion.name_len && name_ptr) { - kversion.name = kmalloc(kversion.name_len, GFP_KERNEL); - if (!kversion.name) - goto out; - } - if (kversion.date_len && date_ptr) { - kversion.date = kmalloc(kversion.date_len, GFP_KERNEL); - if (!kversion.date) - goto out; - } - if (kversion.desc_len && desc_ptr) { - kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL); - if (!kversion.desc) - goto out; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion); - set_fs(old_fs); - - if (!ret) { - if ((kversion.name && - copy_to_user(name_ptr, kversion.name, kversion.name_len)) || - (kversion.date && - copy_to_user(date_ptr, kversion.date, kversion.date_len)) || - (kversion.desc && - copy_to_user(desc_ptr, kversion.desc, kversion.desc_len))) - ret = -EFAULT; - if (put_user(kversion.version_major, &uversion->version_major) || - put_user(kversion.version_minor, &uversion->version_minor) || - put_user(kversion.version_patchlevel, &uversion->version_patchlevel) || - put_user(kversion.name_len, &uversion->name_len) || - put_user(kversion.date_len, &uversion->date_len) || - put_user(kversion.desc_len, &uversion->desc_len)) - ret = -EFAULT; - } - -out: - if (kversion.name) - kfree(kversion.name); - if (kversion.date) - kfree(kversion.date); - if (kversion.desc) - kfree(kversion.desc); - return ret; -} - -typedef struct drm32_unique { - int unique_len; /* Length of unique */ - u32 unique; /* Unique name for driver instantiation */ -} drm32_unique_t; -#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) -#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) - -static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_unique_t *uarg = (drm32_unique_t *)arg; - drm_unique_t karg; - mm_segment_t old_fs; - char *uptr; - u32 tmp; - int ret; - - if (get_user(karg.unique_len, &uarg->unique_len)) - return -EFAULT; - karg.unique = NULL; - - if (get_user(tmp, &uarg->unique)) - return -EFAULT; - - uptr = (char *) A(tmp); - - if (uptr) { - karg.unique = kmalloc(karg.unique_len, GFP_KERNEL); - if (!karg.unique) - return -ENOMEM; - if (cmd == DRM32_IOCTL_SET_UNIQUE && - copy_from_user(karg.unique, uptr, karg.unique_len)) { - kfree(karg.unique); - return -EFAULT; - } - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - if (cmd == DRM32_IOCTL_GET_UNIQUE) - ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg); - else - ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg); - set_fs(old_fs); - - if (!ret) { - if (cmd == DRM32_IOCTL_GET_UNIQUE && - uptr != NULL && - copy_to_user(uptr, karg.unique, karg.unique_len)) - ret = -EFAULT; - if (put_user(karg.unique_len, &uarg->unique_len)) - ret = -EFAULT; - } - - if (karg.unique != NULL) - kfree(karg.unique); - - return ret; -} - -typedef struct drm32_map { - u32 offset; /* Requested physical address (0 for SAREA)*/ - u32 size; /* Requested physical size (bytes) */ - drm_map_type_t type; /* Type of memory to map */ - drm_map_flags_t flags; /* Flags */ - u32 handle; /* User-space: "Handle" to pass to mmap */ - /* Kernel-space: kernel-virtual address */ - int mtrr; /* MTRR slot used */ - /* Private data */ -} drm32_map_t; -#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t) - -static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_map_t *uarg = (drm32_map_t *) arg; - drm_map_t karg; - mm_segment_t old_fs; - u32 tmp; - int ret; - - ret = get_user(karg.offset, &uarg->offset); - ret |= get_user(karg.size, &uarg->size); - ret |= get_user(karg.type, &uarg->type); - ret |= get_user(karg.flags, &uarg->flags); - ret |= get_user(tmp, &uarg->handle); - ret |= get_user(karg.mtrr, &uarg->mtrr); - if (ret) - return -EFAULT; - - karg.handle = (void *) A(tmp); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - ret = put_user(karg.offset, &uarg->offset); - ret |= put_user(karg.size, &uarg->size); - ret |= put_user(karg.type, &uarg->type); - ret |= put_user(karg.flags, &uarg->flags); - tmp = (u32) (long)karg.handle; - ret |= put_user(tmp, &uarg->handle); - ret |= put_user(karg.mtrr, &uarg->mtrr); - if (ret) - ret = -EFAULT; - } - - return ret; -} - -typedef struct drm32_buf_info { - int count; /* Entries in list */ - u32 list; /* (drm_buf_desc_t *) */ -} drm32_buf_info_t; -#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t) - -static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg; - drm_buf_desc_t *ulist; - drm_buf_info_t karg; - mm_segment_t old_fs; - int orig_count, ret; - u32 tmp; - - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->list)) - return -EFAULT; - - ulist = (drm_buf_desc_t *) A(tmp); - - orig_count = karg.count; - - karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL); - if (!karg.list) - return -EFAULT; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - if (karg.count <= orig_count && - (copy_to_user(ulist, karg.list, - karg.count * sizeof(drm_buf_desc_t)))) - ret = -EFAULT; - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } - - kfree(karg.list); - - return ret; -} - -typedef struct drm32_buf_free { - int count; - u32 list; /* (int *) */ -} drm32_buf_free_t; -#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t) - -static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg; - drm_buf_free_t karg; - mm_segment_t old_fs; - int *ulist; - int ret; - u32 tmp; - - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->list)) - return -EFAULT; - - ulist = (int *) A(tmp); - - karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL); - if (!karg.list) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int)))) - goto out; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg); - set_fs(old_fs); - -out: - kfree(karg.list); - - return ret; -} - -typedef struct drm32_buf_pub { - int idx; /* Index into master buflist */ - int total; /* Buffer size */ - int used; /* Amount of buffer in use (for DMA) */ - u32 address; /* Address of buffer (void *) */ -} drm32_buf_pub_t; - -typedef struct drm32_buf_map { - int count; /* Length of buflist */ - u32 virtual; /* Mmaped area in user-virtual (void *) */ - u32 list; /* Buffer information (drm_buf_pub_t *) */ -} drm32_buf_map_t; -#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t) - -static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg; - drm32_buf_pub_t *ulist; - drm_buf_map_t karg; - mm_segment_t old_fs; - int orig_count, ret, i; - u32 tmp1, tmp2; - - if (get_user(karg.count, &uarg->count) || - get_user(tmp1, &uarg->virtual) || - get_user(tmp2, &uarg->list)) - return -EFAULT; - - karg.virtual = (void *) A(tmp1); - ulist = (drm32_buf_pub_t *) A(tmp2); - - orig_count = karg.count; - - karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL); - if (!karg.list) - return -ENOMEM; - - ret = -EFAULT; - for (i = 0; i < karg.count; i++) { - if (get_user(karg.list[i].idx, &ulist[i].idx) || - get_user(karg.list[i].total, &ulist[i].total) || - get_user(karg.list[i].used, &ulist[i].used) || - get_user(tmp1, &ulist[i].address)) - goto out; - - karg.list[i].address = (void *) A(tmp1); - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - for (i = 0; i < orig_count; i++) { - tmp1 = (u32) (long) karg.list[i].address; - if (put_user(karg.list[i].idx, &ulist[i].idx) || - put_user(karg.list[i].total, &ulist[i].total) || - put_user(karg.list[i].used, &ulist[i].used) || - put_user(tmp1, &ulist[i].address)) { - ret = -EFAULT; - goto out; - } - } - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } - -out: - kfree(karg.list); - return ret; -} - -typedef struct drm32_dma { - /* Indices here refer to the offset into - buflist in drm_buf_get_t. */ - int context; /* Context handle */ - int send_count; /* Number of buffers to send */ - u32 send_indices; /* List of handles to buffers (int *) */ - u32 send_sizes; /* Lengths of data to send (int *) */ - drm_dma_flags_t flags; /* Flags */ - int request_count; /* Number of buffers requested */ - int request_size; /* Desired size for buffers */ - u32 request_indices; /* Buffer information (int *) */ - u32 request_sizes; /* (int *) */ - int granted_count; /* Number of buffers granted */ -} drm32_dma_t; -#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t) - -/* RED PEN The DRM layer blindly dereferences the send/request - * indice/size arrays even though they are userland - * pointers. -DaveM - */ -static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_dma_t *uarg = (drm32_dma_t *) arg; - int *u_si, *u_ss, *u_ri, *u_rs; - drm_dma_t karg; - mm_segment_t old_fs; - int ret; - u32 tmp1, tmp2, tmp3, tmp4; - - karg.send_indices = karg.send_sizes = NULL; - karg.request_indices = karg.request_sizes = NULL; - - if (get_user(karg.context, &uarg->context) || - get_user(karg.send_count, &uarg->send_count) || - get_user(tmp1, &uarg->send_indices) || - get_user(tmp2, &uarg->send_sizes) || - get_user(karg.flags, &uarg->flags) || - get_user(karg.request_count, &uarg->request_count) || - get_user(karg.request_size, &uarg->request_size) || - get_user(tmp3, &uarg->request_indices) || - get_user(tmp4, &uarg->request_sizes) || - get_user(karg.granted_count, &uarg->granted_count)) - return -EFAULT; - - u_si = (int *) A(tmp1); - u_ss = (int *) A(tmp2); - u_ri = (int *) A(tmp3); - u_rs = (int *) A(tmp4); - - if (karg.send_count) { - karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); - karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); - - ret = -ENOMEM; - if (!karg.send_indices || !karg.send_sizes) - goto out; - - ret = -EFAULT; - if (copy_from_user(karg.send_indices, u_si, - (karg.send_count * sizeof(int))) || - copy_from_user(karg.send_sizes, u_ss, - (karg.send_count * sizeof(int)))) - goto out; - } - - if (karg.request_count) { - karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); - karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); - - ret = -ENOMEM; - if (!karg.request_indices || !karg.request_sizes) - goto out; - - ret = -EFAULT; - if (copy_from_user(karg.request_indices, u_ri, - (karg.request_count * sizeof(int))) || - copy_from_user(karg.request_sizes, u_rs, - (karg.request_count * sizeof(int)))) - goto out; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - if (put_user(karg.context, &uarg->context) || - put_user(karg.send_count, &uarg->send_count) || - put_user(karg.flags, &uarg->flags) || - put_user(karg.request_count, &uarg->request_count) || - put_user(karg.request_size, &uarg->request_size) || - put_user(karg.granted_count, &uarg->granted_count)) - ret = -EFAULT; - - if (karg.send_count) { - if (copy_to_user(u_si, karg.send_indices, - (karg.send_count * sizeof(int))) || - copy_to_user(u_ss, karg.send_sizes, - (karg.send_count * sizeof(int)))) - ret = -EFAULT; - } - if (karg.request_count) { - if (copy_to_user(u_ri, karg.request_indices, - (karg.request_count * sizeof(int))) || - copy_to_user(u_rs, karg.request_sizes, - (karg.request_count * sizeof(int)))) - ret = -EFAULT; - } - } - -out: - if (karg.send_indices) - kfree(karg.send_indices); - if (karg.send_sizes) - kfree(karg.send_sizes); - if (karg.request_indices) - kfree(karg.request_indices); - if (karg.request_sizes) - kfree(karg.request_sizes); - - return ret; -} - -typedef struct drm32_ctx_res { - int count; - u32 contexts; /* (drm_ctx_t *) */ -} drm32_ctx_res_t; -#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t) - -static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg; - drm_ctx_t *ulist; - drm_ctx_res_t karg; - mm_segment_t old_fs; - int orig_count, ret; - u32 tmp; - - karg.contexts = NULL; - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->contexts)) - return -EFAULT; - - ulist = (drm_ctx_t *) A(tmp); - - orig_count = karg.count; - if (karg.count && ulist) { - karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL); - if (!karg.contexts) - return -ENOMEM; - if (copy_from_user(karg.contexts, ulist, - (karg.count * sizeof(drm_ctx_t)))) { - kfree(karg.contexts); - return -EFAULT; - } - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - if (orig_count) { - if (copy_to_user(ulist, karg.contexts, - (orig_count * sizeof(drm_ctx_t)))) - ret = -EFAULT; - } - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } - - if (karg.contexts) - kfree(karg.contexts); - - return ret; -} - -#endif - -static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} - -static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - /* The mkswap binary hard codes it to Intel value :-((( */ - return w_long(fd, BLKGETSIZE, arg); -} - -struct blkpg_ioctl_arg32 { - int op; - int flags; - int datalen; - u32 data; -}; - -static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg) -{ - struct blkpg_ioctl_arg a; - struct blkpg_partition p; - int err; - mm_segment_t old_fs = get_fs(); - - err = get_user(a.op, &arg->op); - err |= __get_user(a.flags, &arg->flags); - err |= __get_user(a.datalen, &arg->datalen); - err |= __get_user((long)a.data, &arg->data); - if (err) return err; - switch (a.op) { - case BLKPG_ADD_PARTITION: - case BLKPG_DEL_PARTITION: - if (a.datalen < sizeof(struct blkpg_partition)) - return -EINVAL; - if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) - return -EFAULT; - a.data = &p; - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&a); - set_fs (old_fs); - default: - return -EINVAL; - } - return err; -} - -static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); -} - struct usbdevfs_ctrltransfer32 { __u8 bRequestType; __u8 bRequest; @@ -3557,867 +747,34 @@ return err; } -struct mtd_oob_buf32 { - u32 start; - u32 length; - u32 ptr; /* unsigned char* */ -}; - -#define MEMWRITEOOB32 _IOWR('M',3,struct mtd_oob_buf32) -#define MEMREADOOB32 _IOWR('M',4,struct mtd_oob_buf32) - -static inline int -mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct mtd_oob_buf32 *uarg = (struct mtd_oob_buf32 *)arg; - struct mtd_oob_buf karg; - u32 tmp; - char *ptr; - int ret; - - if (get_user(karg.start, &uarg->start) || - get_user(karg.length, &uarg->length) || - get_user(tmp, &uarg->ptr)) - return -EFAULT; - - ptr = (char *)A(tmp); - if (0 >= karg.length) - return -EINVAL; - - karg.ptr = kmalloc(karg.length, GFP_KERNEL); - if (NULL == karg.ptr) - return -ENOMEM; - - if (copy_from_user(karg.ptr, ptr, karg.length)) { - kfree(karg.ptr); - return -EFAULT; - } - - set_fs(KERNEL_DS); - if (MEMREADOOB32 == cmd) - ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg); - else if (MEMWRITEOOB32 == cmd) - ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg); - else - ret = -EINVAL; - set_fs(old_fs); - - if (0 == ret && cmd == MEMREADOOB32) { - ret = copy_to_user(ptr, karg.ptr, karg.length); - ret |= put_user(karg.start, &uarg->start); - ret |= put_user(karg.length, &uarg->length); - } - - kfree(karg.ptr); - return ((0 == ret) ? 0 : -EFAULT); -} - -/* Fix sizeof(sizeof()) breakage */ -#define BLKBSZGET_32 _IOR(0x12,112,int) -#define BLKBSZSET_32 _IOW(0x12,113,int) -#define BLKGETSIZE64_32 _IOR(0x12,114,int) - -static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZGET, arg); -} - -static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZSET, arg); -} - -static int do_blkgetsize64(unsigned int fd, unsigned int cmd, - unsigned long arg) -{ - return sys_ioctl(fd, BLKGETSIZE64, arg); -} - -/* Bluetooth ioctls */ -#define HCIUARTSETPROTO _IOW('U', 200, int) -#define HCIUARTGETPROTO _IOR('U', 201, int) - -#define BNEPCONNADD _IOW('B', 200, int) -#define BNEPCONNDEL _IOW('B', 201, int) -#define BNEPGETCONNLIST _IOR('B', 210, int) -#define BNEPGETCONNINFO _IOR('B', 211, int) - -struct ioctl_trans { - unsigned long cmd; - unsigned long handler; - unsigned long next; -}; - -#define COMPATIBLE_IOCTL(cmd) { cmd, (unsigned long)sys_ioctl, 0 }, +#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 }, +#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { cmd, (unsigned long)handler, 0 }, - -#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) -#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) - -static struct ioctl_trans ioctl_translations[] = { - /* List here explicitly which ioctl's need translation, - * all others default to calling sys_ioctl(). - */ -/* Big T */ -COMPATIBLE_IOCTL(TCGETA) -COMPATIBLE_IOCTL(TCSETA) -COMPATIBLE_IOCTL(TCSETAW) -COMPATIBLE_IOCTL(TCSETAF) -COMPATIBLE_IOCTL(TCSBRK) +#define IOCTL_TABLE_START \ + struct ioctl_trans ioctl_start[] = { +#define IOCTL_TABLE_END \ + }; struct ioctl_trans ioctl_end[0]; + +IOCTL_TABLE_START +#include +#define DECLARES +#include "compat_ioctl.c" COMPATIBLE_IOCTL(TCSBRKP) -COMPATIBLE_IOCTL(TCXONC) -COMPATIBLE_IOCTL(TCFLSH) -COMPATIBLE_IOCTL(TCGETS) -COMPATIBLE_IOCTL(TCSETS) -COMPATIBLE_IOCTL(TCSETSW) -COMPATIBLE_IOCTL(TCSETSF) -COMPATIBLE_IOCTL(TIOCLINUX) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) -/* Little t */ -COMPATIBLE_IOCTL(TIOCGETD) -COMPATIBLE_IOCTL(TIOCSETD) -COMPATIBLE_IOCTL(TIOCEXCL) -COMPATIBLE_IOCTL(TIOCNXCL) -COMPATIBLE_IOCTL(TIOCCONS) -COMPATIBLE_IOCTL(TIOCGSOFTCAR) -COMPATIBLE_IOCTL(TIOCSSOFTCAR) -COMPATIBLE_IOCTL(TIOCSWINSZ) -COMPATIBLE_IOCTL(TIOCGWINSZ) -COMPATIBLE_IOCTL(TIOCMGET) -COMPATIBLE_IOCTL(TIOCMBIC) -COMPATIBLE_IOCTL(TIOCMBIS) -COMPATIBLE_IOCTL(TIOCMSET) -COMPATIBLE_IOCTL(TIOCPKT) -COMPATIBLE_IOCTL(TIOCNOTTY) -COMPATIBLE_IOCTL(TIOCSTI) -COMPATIBLE_IOCTL(TIOCOUTQ) -COMPATIBLE_IOCTL(TIOCSPGRP) -COMPATIBLE_IOCTL(TIOCGPGRP) -COMPATIBLE_IOCTL(TIOCSCTTY) -COMPATIBLE_IOCTL(TIOCGPTN) -COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCGSERIAL) COMPATIBLE_IOCTL(TIOCSSERIAL) -COMPATIBLE_IOCTL(TIOCSERGETLSR) COMPATIBLE_IOCTL(TIOCSLTC) -/* Big F */ -COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) -COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP) -COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP) #if 0 COMPATIBLE_IOCTL(FBIOBLANK) #endif -/* Little f */ -COMPATIBLE_IOCTL(FIOCLEX) -COMPATIBLE_IOCTL(FIONCLEX) -COMPATIBLE_IOCTL(FIOASYNC) -COMPATIBLE_IOCTL(FIONBIO) -COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ -/* 0x00 */ -COMPATIBLE_IOCTL(FIBMAP) -COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x03 -- HD/IDE ioctl's used by hdparm and friends. - * Some need translations, these do not. - */ -COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) -COMPATIBLE_IOCTL(HDIO_SET_DMA) -COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR) -COMPATIBLE_IOCTL(HDIO_SET_NOWERR) -COMPATIBLE_IOCTL(HDIO_SET_32BIT) -COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT) -COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) -COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) -COMPATIBLE_IOCTL(HDIO_SET_NICE) -/* 0x02 -- Floppy ioctls */ -COMPATIBLE_IOCTL(FDMSGON) -COMPATIBLE_IOCTL(FDMSGOFF) -COMPATIBLE_IOCTL(FDSETEMSGTRESH) -COMPATIBLE_IOCTL(FDFLUSH) -COMPATIBLE_IOCTL(FDWERRORCLR) -COMPATIBLE_IOCTL(FDSETMAXERRS) -COMPATIBLE_IOCTL(FDGETMAXERRS) -COMPATIBLE_IOCTL(FDGETDRVTYP) -COMPATIBLE_IOCTL(FDEJECT) -COMPATIBLE_IOCTL(FDCLRPRM) -COMPATIBLE_IOCTL(FDFMTBEG) -COMPATIBLE_IOCTL(FDFMTEND) -COMPATIBLE_IOCTL(FDRESET) -COMPATIBLE_IOCTL(FDTWADDLE) -COMPATIBLE_IOCTL(FDFMTTRK) -COMPATIBLE_IOCTL(FDRAWCMD) -/* 0x12 */ -COMPATIBLE_IOCTL(BLKROSET) -COMPATIBLE_IOCTL(BLKROGET) -COMPATIBLE_IOCTL(BLKRRPART) -COMPATIBLE_IOCTL(BLKFLSBUF) -COMPATIBLE_IOCTL(BLKSECTSET) -COMPATIBLE_IOCTL(BLKSSZGET) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKFRASET) -/* RAID */ -COMPATIBLE_IOCTL(RAID_VERSION) -COMPATIBLE_IOCTL(GET_ARRAY_INFO) -COMPATIBLE_IOCTL(GET_DISK_INFO) -COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) -COMPATIBLE_IOCTL(CLEAR_ARRAY) -COMPATIBLE_IOCTL(ADD_NEW_DISK) -COMPATIBLE_IOCTL(HOT_REMOVE_DISK) -COMPATIBLE_IOCTL(SET_ARRAY_INFO) -COMPATIBLE_IOCTL(SET_DISK_INFO) -COMPATIBLE_IOCTL(WRITE_RAID_INFO) -COMPATIBLE_IOCTL(UNPROTECT_ARRAY) -COMPATIBLE_IOCTL(PROTECT_ARRAY) -COMPATIBLE_IOCTL(HOT_ADD_DISK) -COMPATIBLE_IOCTL(SET_DISK_FAULTY) -COMPATIBLE_IOCTL(RUN_ARRAY) -COMPATIBLE_IOCTL(START_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY_RO) -COMPATIBLE_IOCTL(RESTART_ARRAY_RW) -/* Big K */ -COMPATIBLE_IOCTL(PIO_FONT) -COMPATIBLE_IOCTL(GIO_FONT) -COMPATIBLE_IOCTL(KDSIGACCEPT) -COMPATIBLE_IOCTL(KDGETKEYCODE) -COMPATIBLE_IOCTL(KDSETKEYCODE) -COMPATIBLE_IOCTL(KIOCSOUND) -COMPATIBLE_IOCTL(KDMKTONE) -COMPATIBLE_IOCTL(KDGKBTYPE) -COMPATIBLE_IOCTL(KDSETMODE) -COMPATIBLE_IOCTL(KDGETMODE) -COMPATIBLE_IOCTL(KDSKBMODE) -COMPATIBLE_IOCTL(KDGKBMODE) -COMPATIBLE_IOCTL(KDSKBMETA) -COMPATIBLE_IOCTL(KDGKBMETA) -COMPATIBLE_IOCTL(KDGKBENT) -COMPATIBLE_IOCTL(KDSKBENT) -COMPATIBLE_IOCTL(KDGKBSENT) -COMPATIBLE_IOCTL(KDSKBSENT) -COMPATIBLE_IOCTL(KDGKBDIACR) -COMPATIBLE_IOCTL(KDKBDREP) -COMPATIBLE_IOCTL(KDSKBDIACR) -COMPATIBLE_IOCTL(KDGKBLED) -COMPATIBLE_IOCTL(KDSKBLED) -COMPATIBLE_IOCTL(KDGETLED) -COMPATIBLE_IOCTL(KDSETLED) -COMPATIBLE_IOCTL(GIO_SCRNMAP) -COMPATIBLE_IOCTL(PIO_SCRNMAP) -COMPATIBLE_IOCTL(GIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_FONTRESET) -COMPATIBLE_IOCTL(PIO_UNIMAPCLR) -/* Big S */ -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) -COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) -/* Big T */ -COMPATIBLE_IOCTL(TUNSETNOCSUM) -COMPATIBLE_IOCTL(TUNSETDEBUG) -COMPATIBLE_IOCTL(TUNSETIFF) -COMPATIBLE_IOCTL(TUNSETPERSIST) -COMPATIBLE_IOCTL(TUNSETOWNER) -/* Big V */ -COMPATIBLE_IOCTL(VT_SETMODE) -COMPATIBLE_IOCTL(VT_GETMODE) -COMPATIBLE_IOCTL(VT_GETSTATE) -COMPATIBLE_IOCTL(VT_OPENQRY) -COMPATIBLE_IOCTL(VT_ACTIVATE) -COMPATIBLE_IOCTL(VT_WAITACTIVE) -COMPATIBLE_IOCTL(VT_RELDISP) -COMPATIBLE_IOCTL(VT_DISALLOCATE) -COMPATIBLE_IOCTL(VT_RESIZE) -COMPATIBLE_IOCTL(VT_RESIZEX) -COMPATIBLE_IOCTL(VT_LOCKSWITCH) -COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -/* Little v, the video4linux ioctls */ -COMPATIBLE_IOCTL(VIDIOCGCAP) -COMPATIBLE_IOCTL(VIDIOCGCHAN) -COMPATIBLE_IOCTL(VIDIOCSCHAN) -COMPATIBLE_IOCTL(VIDIOCGPICT) -COMPATIBLE_IOCTL(VIDIOCSPICT) -COMPATIBLE_IOCTL(VIDIOCCAPTURE) -COMPATIBLE_IOCTL(VIDIOCKEY) -COMPATIBLE_IOCTL(VIDIOCGAUDIO) -COMPATIBLE_IOCTL(VIDIOCSAUDIO) -COMPATIBLE_IOCTL(VIDIOCSYNC) -COMPATIBLE_IOCTL(VIDIOCMCAPTURE) -COMPATIBLE_IOCTL(VIDIOCGMBUF) -COMPATIBLE_IOCTL(VIDIOCGUNIT) -COMPATIBLE_IOCTL(VIDIOCGCAPTURE) -COMPATIBLE_IOCTL(VIDIOCSCAPTURE) -/* BTTV specific... */ -COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256])) -COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256])) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)) -COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */ -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int)) /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) -COMPATIBLE_IOCTL(RTC_ALM_READ) -COMPATIBLE_IOCTL(RTC_RD_TIME) -COMPATIBLE_IOCTL(RTC_SET_TIME) -COMPATIBLE_IOCTL(RTC_WKALM_SET) -COMPATIBLE_IOCTL(RTC_WKALM_RD) -/* Little m */ -COMPATIBLE_IOCTL(MTIOCTOP) -/* Socket level stuff */ -COMPATIBLE_IOCTL(FIOSETOWN) -COMPATIBLE_IOCTL(SIOCSPGRP) -COMPATIBLE_IOCTL(FIOGETOWN) -COMPATIBLE_IOCTL(SIOCGPGRP) -COMPATIBLE_IOCTL(SIOCATMARK) -COMPATIBLE_IOCTL(SIOCSIFLINK) -COMPATIBLE_IOCTL(SIOCSIFENCAP) -COMPATIBLE_IOCTL(SIOCGIFENCAP) -COMPATIBLE_IOCTL(SIOCSIFBR) -COMPATIBLE_IOCTL(SIOCGIFBR) -COMPATIBLE_IOCTL(SIOCSARP) -COMPATIBLE_IOCTL(SIOCGARP) -COMPATIBLE_IOCTL(SIOCDARP) -COMPATIBLE_IOCTL(SIOCSRARP) -COMPATIBLE_IOCTL(SIOCGRARP) -COMPATIBLE_IOCTL(SIOCDRARP) -COMPATIBLE_IOCTL(SIOCADDDLCI) -COMPATIBLE_IOCTL(SIOCDELDLCI) -COMPATIBLE_IOCTL(SIOCGMIIPHY) -COMPATIBLE_IOCTL(SIOCGMIIREG) -COMPATIBLE_IOCTL(SIOCSMIIREG) -COMPATIBLE_IOCTL(SIOCGIFVLAN) -COMPATIBLE_IOCTL(SIOCSIFVLAN) -/* SG stuff */ -COMPATIBLE_IOCTL(SG_SET_TIMEOUT) -COMPATIBLE_IOCTL(SG_GET_TIMEOUT) -COMPATIBLE_IOCTL(SG_EMULATED_HOST) -COMPATIBLE_IOCTL(SG_SET_TRANSFORM) -COMPATIBLE_IOCTL(SG_GET_TRANSFORM) -COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_SCSI_ID) -COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) -COMPATIBLE_IOCTL(SG_GET_LOW_DMA) -COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) -COMPATIBLE_IOCTL(SG_SET_DEBUG) -COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) -COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) -COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) -COMPATIBLE_IOCTL(SG_SCSI_RESET) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) -COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) -/* PPP stuff */ -COMPATIBLE_IOCTL(PPPIOCGFLAGS) -COMPATIBLE_IOCTL(PPPIOCSFLAGS) -COMPATIBLE_IOCTL(PPPIOCGASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGUNIT) -COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGMRU) -COMPATIBLE_IOCTL(PPPIOCSMRU) -COMPATIBLE_IOCTL(PPPIOCSMAXCID) -COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) -COMPATIBLE_IOCTL(LPGETSTATUS) -COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCXFERUNIT) -COMPATIBLE_IOCTL(PPPIOCGNPMODE) -COMPATIBLE_IOCTL(PPPIOCSNPMODE) -COMPATIBLE_IOCTL(PPPIOCGDEBUG) -COMPATIBLE_IOCTL(PPPIOCSDEBUG) -COMPATIBLE_IOCTL(PPPIOCNEWUNIT) -COMPATIBLE_IOCTL(PPPIOCATTACH) -COMPATIBLE_IOCTL(PPPIOCDETACH) -COMPATIBLE_IOCTL(PPPIOCSMRRU) -COMPATIBLE_IOCTL(PPPIOCCONNECT) -COMPATIBLE_IOCTL(PPPIOCDISCONN) -COMPATIBLE_IOCTL(PPPIOCATTCHAN) -COMPATIBLE_IOCTL(PPPIOCGCHAN) -/* PPPOX */ -COMPATIBLE_IOCTL(PPPOEIOCSFWD) -COMPATIBLE_IOCTL(PPPOEIOCDFWD) -/* CDROM stuff */ -COMPATIBLE_IOCTL(CDROMPAUSE) -COMPATIBLE_IOCTL(CDROMRESUME) -COMPATIBLE_IOCTL(CDROMPLAYMSF) -COMPATIBLE_IOCTL(CDROMPLAYTRKIND) -COMPATIBLE_IOCTL(CDROMREADTOCHDR) -COMPATIBLE_IOCTL(CDROMREADTOCENTRY) -COMPATIBLE_IOCTL(CDROMSTOP) -COMPATIBLE_IOCTL(CDROMSTART) -COMPATIBLE_IOCTL(CDROMEJECT) -COMPATIBLE_IOCTL(CDROMVOLCTRL) -COMPATIBLE_IOCTL(CDROMSUBCHNL) -COMPATIBLE_IOCTL(CDROMEJECT_SW) -COMPATIBLE_IOCTL(CDROMMULTISESSION) -COMPATIBLE_IOCTL(CDROM_GET_MCN) -COMPATIBLE_IOCTL(CDROMRESET) -COMPATIBLE_IOCTL(CDROMVOLREAD) -COMPATIBLE_IOCTL(CDROMSEEK) -COMPATIBLE_IOCTL(CDROMPLAYBLK) -COMPATIBLE_IOCTL(CDROMCLOSETRAY) -COMPATIBLE_IOCTL(CDROM_SET_OPTIONS) -COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS) -COMPATIBLE_IOCTL(CDROM_SELECT_SPEED) -COMPATIBLE_IOCTL(CDROM_SELECT_DISC) -COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED) -COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS) -COMPATIBLE_IOCTL(CDROM_DISC_STATUS) -COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) -COMPATIBLE_IOCTL(CDROM_LOCKDOOR) -COMPATIBLE_IOCTL(CDROM_DEBUG) -COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) -/* DVD ioctls */ -COMPATIBLE_IOCTL(DVD_READ_STRUCT) -COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) -COMPATIBLE_IOCTL(DVD_AUTH) -/* Big L */ -COMPATIBLE_IOCTL(LOOP_SET_FD) -COMPATIBLE_IOCTL(LOOP_CLR_FD) -/* Big Q for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET) -COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE) -COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR) -COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI) -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS) -COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL) -COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC) -COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE) -/* Big T for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE) -COMPATIBLE_IOCTL(SNDCTL_TMR_START) -COMPATIBLE_IOCTL(SNDCTL_TMR_STOP) -COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE) -COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO) -COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE) -COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME) -COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT) -/* Little m for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD) -/* Big P for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_DSP_RESET) -COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC) -COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED) -COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE) -COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER) -COMPATIBLE_IOCTL(SNDCTL_DSP_POST) -COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR) -/* SNDCTL_DSP_MAPINBUF, XXX needs translation */ -/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */ -COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY) -COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER) -/* Big C for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_COPR_RESET) -COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD) -COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_RUN) -COMPATIBLE_IOCTL(SNDCTL_COPR_HALT) -COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG) -/* Big M for sound/OSS */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE) -/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */ -/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE) -/* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */ -/* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5) -COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS) -COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS) -COMPATIBLE_IOCTL(OSS_GETVERSION) -/* AUTOFS */ -COMPATIBLE_IOCTL(AUTOFS_IOC_READY) -COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) -COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) -COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) -COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) -/* DEVFS */ -COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) -COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK) -/* Raw devices */ -COMPATIBLE_IOCTL(RAW_SETBIND) -COMPATIBLE_IOCTL(RAW_GETBIND) -/* SMB ioctls which do not need any translations */ -COMPATIBLE_IOCTL(SMB_IOC_NEWCONN) -/* NCP ioctls which do not need any translations */ -COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK) -COMPATIBLE_IOCTL(NCP_IOC_GETROOT) -COMPATIBLE_IOCTL(NCP_IOC_SETROOT) -COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL) -COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL) -/* Little a */ -COMPATIBLE_IOCTL(ATMSIGD_CTRL) -COMPATIBLE_IOCTL(ATMARPD_CTRL) -COMPATIBLE_IOCTL(ATMLEC_CTRL) -COMPATIBLE_IOCTL(ATMLEC_MCAST) -COMPATIBLE_IOCTL(ATMLEC_DATA) -COMPATIBLE_IOCTL(ATM_SETSC) -COMPATIBLE_IOCTL(SIOCSIFATMTCP) -COMPATIBLE_IOCTL(SIOCMKCLIP) -COMPATIBLE_IOCTL(ATMARP_MKIP) -COMPATIBLE_IOCTL(ATMARP_SETENTRY) -COMPATIBLE_IOCTL(ATMARP_ENCAP) -COMPATIBLE_IOCTL(ATMTCP_CREATE) -COMPATIBLE_IOCTL(ATMTCP_REMOVE) -COMPATIBLE_IOCTL(ATMMPC_CTRL) -COMPATIBLE_IOCTL(ATMMPC_DATA) -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) -COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) -#endif /* DRM */ -/* Big W */ -/* WIOC_GETSUPPORT not yet implemented -E */ -COMPATIBLE_IOCTL(WDIOC_GETSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETTEMP) -COMPATIBLE_IOCTL(WDIOC_SETOPTIONS) -COMPATIBLE_IOCTL(WDIOC_KEEPALIVE) -/* Big R */ -COMPATIBLE_IOCTL(RNDGETENTCNT) -COMPATIBLE_IOCTL(RNDADDTOENTCNT) -COMPATIBLE_IOCTL(RNDGETPOOL) -COMPATIBLE_IOCTL(RNDADDENTROPY) -COMPATIBLE_IOCTL(RNDZAPENTCNT) -COMPATIBLE_IOCTL(RNDCLEARPOOL) -/* Bluetooth ioctls */ -COMPATIBLE_IOCTL(HCIDEVUP) -COMPATIBLE_IOCTL(HCIDEVDOWN) -COMPATIBLE_IOCTL(HCIDEVRESET) -COMPATIBLE_IOCTL(HCIDEVRESTAT) -COMPATIBLE_IOCTL(HCIGETDEVLIST) -COMPATIBLE_IOCTL(HCIGETDEVINFO) -COMPATIBLE_IOCTL(HCIGETCONNLIST) -COMPATIBLE_IOCTL(HCIGETCONNINFO) -COMPATIBLE_IOCTL(HCISETRAW) -COMPATIBLE_IOCTL(HCISETSCAN) -COMPATIBLE_IOCTL(HCISETAUTH) -COMPATIBLE_IOCTL(HCISETENCRYPT) -COMPATIBLE_IOCTL(HCISETPTYPE) -COMPATIBLE_IOCTL(HCISETLINKPOL) -COMPATIBLE_IOCTL(HCISETLINKMODE) -COMPATIBLE_IOCTL(HCISETACLMTU) -COMPATIBLE_IOCTL(HCISETSCOMTU) -COMPATIBLE_IOCTL(HCIINQUIRY) -COMPATIBLE_IOCTL(HCIUARTSETPROTO) -COMPATIBLE_IOCTL(HCIUARTGETPROTO) -COMPATIBLE_IOCTL(RFCOMMCREATEDEV) -COMPATIBLE_IOCTL(RFCOMMRELEASEDEV) -COMPATIBLE_IOCTL(RFCOMMGETDEVLIST) -COMPATIBLE_IOCTL(RFCOMMGETDEVINFO) -COMPATIBLE_IOCTL(RFCOMMSTEALDLC) -COMPATIBLE_IOCTL(BNEPCONNADD) -COMPATIBLE_IOCTL(BNEPCONNDEL) -COMPATIBLE_IOCTL(BNEPGETCONNLIST) -COMPATIBLE_IOCTL(BNEPGETCONNINFO) -COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) -COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* USB */ -COMPATIBLE_IOCTL(USBDEVFS_RESETEP) -COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION) -COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER) -COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB) -COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO) -COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO) -COMPATIBLE_IOCTL(USBDEVFS_RESET) -COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT) -/* MTD */ -COMPATIBLE_IOCTL(MEMGETINFO) -COMPATIBLE_IOCTL(MEMERASE) -COMPATIBLE_IOCTL(MEMLOCK) -COMPATIBLE_IOCTL(MEMUNLOCK) -COMPATIBLE_IOCTL(MEMGETREGIONCOUNT) -COMPATIBLE_IOCTL(MEMGETREGIONINFO) -/* NBD */ -COMPATIBLE_IOCTL(NBD_SET_SOCK) -COMPATIBLE_IOCTL(NBD_SET_BLKSIZE) -COMPATIBLE_IOCTL(NBD_SET_SIZE) -COMPATIBLE_IOCTL(NBD_DO_IT) -COMPATIBLE_IOCTL(NBD_CLEAR_SOCK) -COMPATIBLE_IOCTL(NBD_CLEAR_QUE) -COMPATIBLE_IOCTL(NBD_PRINT_DEBUG) -COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS) -COMPATIBLE_IOCTL(NBD_DISCONNECT) -/* device-mapper */ -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) + /* And these ioctls need translation */ -HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) -HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) -#ifdef CONFIG_NET -HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) -#endif -HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) -HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc) -HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) -HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) -HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) -HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) -HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl) -HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl) -HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl) -HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl) -HANDLE_IOCTL(SIOCADDRT, routing_ioctl) -HANDLE_IOCTL(SIOCDELRT, routing_ioctl) -/* Note SIOCRTMSG is no longer, so this is safe and - * the user would have seen just an -EINVAL anyways. */ -HANDLE_IOCTL(SIOCRTMSG, ret_einval) -HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) -HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) HANDLE_IOCTL(HDIO_GETGEO_BIG_RAW, hdio_getgeo_big) -HANDLE_IOCTL(BLKGETSIZE, w_long) -HANDLE_IOCTL(BLKRAGET, w_long) -HANDLE_IOCTL(BLKFRAGET, w_long) -HANDLE_IOCTL(0x1260, broken_blkgetsize) -HANDLE_IOCTL(BLKSECTGET, w_long) -HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans) -HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) -HANDLE_IOCTL(SG_IO,sg_ioctl_trans) -HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans) -HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans) -HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans) -HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) -HANDLE_IOCTL(LOOP_SET_STATUS, loop_status) -HANDLE_IOCTL(LOOP_GET_STATUS, loop_status) -HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) -#ifdef CONFIG_VT -HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl) -HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl) -HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl) -HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl) -HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) -HANDLE_IOCTL(FBIOGET_FSCREENINFO, do_fbioget_fscreeninfo_ioctl) -HANDLE_IOCTL(FBIOGETCMAP, do_fbiogetcmap_ioctl) -HANDLE_IOCTL(FBIOPUTCMAP, do_fbioputcmap_ioctl) -#endif -HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl) -HANDLE_IOCTL(VIDIOCGTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGWIN32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSWIN32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl) -/* One SMB ioctl needs translations. */ -HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) + /* NCPFS */ HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest) HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2) @@ -4426,51 +783,12 @@ HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname) HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata) HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata) -HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl) -HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl) -HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl) -HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl) -HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version) -HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique) -HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique) -HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap) -HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs) -HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs) -HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs) -HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma) -HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx) -#endif /* DRM */ + +/* USB devfs */ HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) /*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) -/* take care of sizeof(sizeof()) breakage */ -/* block stuff */ -HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) -HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) -HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) -}; +IOCTL_TABLE_END diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/irq.c Thu Jun 19 00:45:34 2003 @@ -63,8 +63,11 @@ volatile unsigned char *chrp_int_ack_special; static void register_irq_proc (unsigned int irq); -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = - { [0 ... NR_IRQS-1] = { 0, NULL, NULL, 0, SPIN_LOCK_UNLOCKED}}; +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { + [0 ... NR_IRQS-1] = { + .lock = SPIN_LOCK_UNLOCKED + } +}; int ppc_spurious_interrupts = 0; unsigned long lpEvent_count = 0; @@ -380,22 +383,48 @@ return 0; } -static inline void -handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action) +extern char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen); + +static inline void handle_irq_event(int irq, struct pt_regs *regs, + struct irqaction *action) { int status = 0; + int retval = 0; + struct irqaction *first_action = action; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= action->flags; - action->handler(irq, action->dev_id, regs); + retval |= action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); + if (retval != 1) { + static int count = 100; + char name_buf[256]; + if (count) { + count--; + if (retval) { + printk("irq event %d: bogus retval mask %x\n", + irq, retval); + } else { + printk("irq %d: nobody cared!\n", irq); + } + dump_stack(); + printk("handlers:\n"); + action = first_action; + do { + printk("[<%p>]", action->handler); + printk(" (%s)\n", + ppc_find_proc_name((unsigned *)action->handler, name_buf, 256)); + action = action->next; + } while (action); + } + } } /* @@ -566,7 +595,6 @@ once++; ppc_md.init_IRQ(); - if(ppc_md.init_ras_IRQ) ppc_md.init_ras_IRQ(); } static struct proc_dir_entry * root_irq_dir; @@ -675,7 +703,7 @@ #ifdef CONFIG_PPC_ISERIES { unsigned i; - for (i=0; i #include #include +#include .text @@ -439,6 +440,95 @@ blr /* + * identify_cpu, + * In: r3 = base of the cpu_specs array + * r4 = address of cur_cpu_spec + * r5 = relocation offset + */ +_GLOBAL(identify_cpu) + mfpvr r7 +1: + lwz r8,CPU_SPEC_PVR_MASK(r3) + and r8,r8,r7 + lwz r9,CPU_SPEC_PVR_VALUE(r3) + cmplw 0,r9,r8 + beq 1f + addi r3,r3,CPU_SPEC_ENTRY_SIZE + b 1b +1: + add r3,r3,r5 + std r3,0(r4) + blr + +/* + * do_cpu_ftr_fixups - goes through the list of CPU feature fixups + * and writes nop's over sections of code that don't apply for this cpu. + * r3 = data offset (not changed) + */ +_GLOBAL(do_cpu_ftr_fixups) + /* Get CPU 0 features */ + LOADADDR(r6,cur_cpu_spec) + sub r6,r6,r3 + ld r4,0(r6) + sub r4,r4,r3 + ld r4,CPU_SPEC_FEATURES(r4) + /* Get the fixup table */ + LOADADDR(r6,__start___ftr_fixup) + sub r6,r6,r3 + LOADADDR(r7,__stop___ftr_fixup) + sub r7,r7,r3 + /* Do the fixup */ +1: cmpld r6,r7 + bgelr + addi r6,r6,32 + ld r8,-32(r6) /* mask */ + and r8,r8,r4 + ld r9,-24(r6) /* value */ + cmpld r8,r9 + beq 1b + ld r8,-16(r6) /* section begin */ + ld r9,-8(r6) /* section end */ + subf. r9,r8,r9 + beq 1b + /* write nops over the section of code */ + /* todo: if large section, add a branch at the start of it */ + srwi r9,r9,2 + mtctr r9 + sub r8,r8,r3 + lis r0,0x60000000@h /* nop */ +3: stw r0,0(r8) + andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l + beq 2f + dcbst 0,r8 /* suboptimal, but simpler */ + sync + icbi 0,r8 +2: addi r8,r8,4 + bdnz 3b + sync /* additional sync needed on g4 */ + isync + b 1b + +/* + * call_setup_cpu - call the setup_cpu function for this cpu + * r3 = data offset + * + * Setup function is called with: + * r3 = data offset + * r4 = ptr to CPU spec (relocated) + */ +_GLOBAL(call_setup_cpu) + LOADADDR(r4, cur_cpu_spec) + sub r4,r4,r3 + lwz r4,0(r4) # load pointer to cpu_spec + sub r4,r4,r3 # relocate + lwz r6,CPU_SPEC_SETUP(r4) # load function pointer + sub r6,r6,r3 + mtctr r6 + bctr + + + +/* * Create a kernel thread * kernel_thread(fn, arg, flags) */ @@ -603,7 +693,7 @@ .llong .sys_ni_syscall /* old profil syscall */ .llong .compat_sys_statfs .llong .compat_sys_fstatfs /* 100 */ - .llong .sys_ioperm + .llong .sys_ni_syscall /* old ioperm syscall */ .llong .compat_sys_socketcall .llong .sys32_syslog .llong .compat_sys_setitimer @@ -729,11 +819,11 @@ .llong .sys_ni_syscall .llong .sys_ni_syscall /* 225 - reserved for tux */ .llong .sys32_sendfile64 - .llong .sys_ni_syscall /* reserved for sys_io_setup */ - .llong .sys_ni_syscall /* reserved for sys_io_destroy */ - .llong .sys_ni_syscall /* reserved for sys_io_getevents */ - .llong .sys_ni_syscall /* 230 - reserved for sys_io_submit */ - .llong .sys_ni_syscall /* reserved for sys_io_cancel */ + .llong .sys32_io_setup + .llong .sys_io_destroy + .llong .sys32_io_getevents + .llong .sys32_io_submit + .llong .sys_io_cancel .llong .sys_set_tid_address .llong .ppc32_fadvise64 .llong .sys_exit_group @@ -846,7 +936,7 @@ .llong .sys_ni_syscall /* old profil syscall holder */ .llong .sys_statfs .llong .sys_fstatfs /* 100 */ - .llong .sys_ioperm + .llong .sys_ni_syscall /* old ioperm syscall */ .llong .sys_socketcall .llong .sys_syslog .llong .sys_setitimer diff -Nru a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c --- a/arch/ppc64/kernel/module.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/module.c Thu Jun 19 00:45:34 2003 @@ -20,6 +20,8 @@ #include #include #include +#include +#include /* FIXME: We don't do .init separately. To do this, we'd need to have a separate r2 value in the init and core section, and stub between @@ -374,15 +376,57 @@ return 0; } -/* In arch/ppc64/mm/extable.c */ -extern void sort_ex_table(struct exception_table_entry *start, - struct exception_table_entry *finish); +LIST_HEAD(module_bug_list); int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) + const Elf_Shdr *sechdrs, struct module *me) { - sort_ex_table(me->extable.entry, - me->extable.entry + me->extable.num_entries); + char *secstrings; + unsigned int i; + + me->arch.bug_table = NULL; + me->arch.num_bugs = 0; + + /* Find the __bug_table section, if present */ + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) { + if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) + continue; + me->arch.bug_table = (void *) sechdrs[i].sh_addr; + me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); + break; + } + + /* + * Strictly speaking this should have a spinlock to protect against + * traversals, but since we only traverse on BUG()s, a spinlock + * could potentially lead to deadlock and thus be counter-productive. + */ + list_add(&me->arch.bug_list, &module_bug_list); + + sort_ex_table((struct exception_table_entry *)me->extable, + (struct exception_table_entry *)me->extable + + me->num_exentries); + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ + list_del(&mod->arch.bug_list); +} + +struct bug_entry *module_find_bug(unsigned long bugaddr) +{ + struct mod_arch_specific *mod; + unsigned int i; + struct bug_entry *bug; + + list_for_each_entry(mod, &module_bug_list, bug_list) { + bug = mod->bug_table; + for (i = 0; i < mod->num_bugs; ++i, ++bug) + if (bugaddr == bug->bug_addr) + return bug; + } + return NULL; } diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c --- a/arch/ppc64/kernel/pacaData.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/pacaData.c Thu Jun 19 00:45:34 2003 @@ -63,7 +63,7 @@ (&paca[number].exception_stack[0]) - EXC_FRAME_SIZE, \ } -struct paca_struct paca[MAX_PACAS] __page_aligned = { +struct paca_struct paca[NR_CPUS] __page_aligned = { #ifdef CONFIG_PPC_ISERIES PACAINITDATA( 0, 1, &xItLpQueue, 0, 0xc000000000005000), #else @@ -100,6 +100,7 @@ PACAINITDATA(29, 0, 0, 0, 0), PACAINITDATA(30, 0, 0, 0, 0), PACAINITDATA(31, 0, 0, 0, 0), +#if NR_CPUS > 32 PACAINITDATA(32, 0, 0, 0, 0), PACAINITDATA(33, 0, 0, 0, 0), PACAINITDATA(34, 0, 0, 0, 0), @@ -115,5 +116,22 @@ PACAINITDATA(44, 0, 0, 0, 0), PACAINITDATA(45, 0, 0, 0, 0), PACAINITDATA(46, 0, 0, 0, 0), - PACAINITDATA(47, 0, 0, 0, 0) + PACAINITDATA(47, 0, 0, 0, 0), + PACAINITDATA(48, 0, 0, 0, 0), + PACAINITDATA(49, 0, 0, 0, 0), + PACAINITDATA(50, 0, 0, 0, 0), + PACAINITDATA(51, 0, 0, 0, 0), + PACAINITDATA(52, 0, 0, 0, 0), + PACAINITDATA(53, 0, 0, 0, 0), + PACAINITDATA(54, 0, 0, 0, 0), + PACAINITDATA(55, 0, 0, 0, 0), + PACAINITDATA(56, 0, 0, 0, 0), + PACAINITDATA(57, 0, 0, 0, 0), + PACAINITDATA(58, 0, 0, 0, 0), + PACAINITDATA(59, 0, 0, 0, 0), + PACAINITDATA(60, 0, 0, 0, 0), + PACAINITDATA(61, 0, 0, 0, 0), + PACAINITDATA(62, 0, 0, 0, 0), + PACAINITDATA(63, 0, 0, 0, 0), +#endif }; diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/pci.c Thu Jun 19 00:45:34 2003 @@ -116,14 +116,14 @@ */ struct pci_dev *pci_find_dev_by_addr(unsigned long addr) { - struct pci_dev *dev; + struct pci_dev *dev = NULL; int i; unsigned long ioaddr; ioaddr = (addr > isa_io_base) ? addr - isa_io_base : 0; - pci_for_each_dev(dev) { - if ((dev->class >> 8) == PCI_BASE_CLASS_BRIDGE) + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) continue; for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { unsigned long start = pci_resource_start(dev,i); @@ -370,11 +370,11 @@ } /* - * Return the index of the PCI controller for device pdev. + * Return the domain number for this bus. */ -int pci_controller_num(struct pci_dev *dev) +int pci_domain_nr(struct pci_bus *bus) { - struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); return hose->global_number; } diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/pci_dma.c Thu Jun 19 00:45:34 2003 @@ -134,7 +134,7 @@ dev = ppc64_isabridge_dev; if (!dev) return NULL; - if (naca->platform == PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform == PLATFORM_ISERIES_LPAR) { return ISERIES_DEVNODE(dev)->DevTceTable; } else { return PCI_GET_DN(dev)->tce_table; @@ -710,12 +710,6 @@ for (ln=bus_list->next; ln != bus_list; ln=ln->next) { bus = pci_bus_b(ln); busdn = PCI_GET_DN(bus); - /* NOTE: there should never be a window declared on a bus when - * child devices also have a window. If this should ever be - * architected, we probably want children to have priority. - * In reality, the PHB containing ISA has the property, but otherwise - * it is the pci-bridges that have the property. - */ dma_window = (u32 *)get_property(busdn, "ibm,dma-window", 0); if (dma_window) { /* Bussubno hasn't been copied yet. @@ -723,16 +717,17 @@ */ busdn->bussubno = bus->number; create_pci_bus_tce_table((unsigned long)busdn); - } else - create_tce_tables_for_busesLP(&bus->children); + } + /* look for a window on a bridge even if the PHB had one */ + create_tce_tables_for_busesLP(&bus->children); } } void create_tce_tables(void) { - struct pci_dev *dev; + struct pci_dev *dev = NULL; struct device_node *dn, *mydn; - if (naca->platform == PLATFORM_PSERIES_LPAR) { + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { create_tce_tables_for_busesLP(&pci_root_buses); } else { @@ -742,7 +737,7 @@ * pci device_node. This means get_tce_table() won't need to search * up the device tree to find it. */ - pci_for_each_dev(dev) { + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { mydn = dn = PCI_GET_DN(dev); while (dn && dn->tce_table == NULL) dn = dn->parent; @@ -773,7 +768,7 @@ /* - Tce Table Share between buses, */ /* - Tce Table per logical slot. */ /*****************************************************************/ - if(naca->platform == PLATFORM_ISERIES_LPAR) { + if(systemcfg->platform == PLATFORM_ISERIES_LPAR) { struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)token; getTceTableParmsiSeries(DevNode,newTceTable); @@ -797,7 +792,7 @@ dn = (struct device_node *)token; phb = dn->phb; - if (naca->platform == PLATFORM_PSERIES) + if (systemcfg->platform == PLATFORM_PSERIES) getTceTableParmsPSeries(phb, dn, newTceTable); else getTceTableParmsPSeriesLP(phb, dn, newTceTable); @@ -1135,7 +1130,8 @@ /* Client asked for way to much space. This is checked later anyway */ /* It is easier to debug here for the drivers than in the tce tables.*/ if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_unmap_single 0x%lx size to large: 0x%lx \n",dma_handle,size); + printk("PCI_DMA: pci_unmap_single 0x%lx size too" + " large: 0x%lx \n", (long)dma_handle, (long)size); return; } diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/process.c Thu Jun 19 00:45:34 2003 @@ -45,6 +45,7 @@ #include #include #include +#include struct task_struct *last_task_used_math = NULL; @@ -67,18 +68,34 @@ #endif /* CONFIG_SMP */ } -int -dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) +#ifdef CONFIG_SMP +static void smp_unlazy_onefpu(void *arg) { - /* - * XXX temporary workaround until threaded coredumps for ppc64 - * are implemented - Anton - */ + struct pt_regs *regs = current->thread.regs; + if (!regs) - return 0; + return; if (regs->msr & MSR_FP) giveup_fpu(current); - memcpy(fpregs, ¤t->thread.fpr[0], sizeof(*fpregs)); +} + +void dump_smp_unlazy_fpu(void) +{ + smp_call_function(smp_unlazy_onefpu, NULL, 1, 1); +} +#endif + +int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) +{ + struct pt_regs *regs = tsk->thread.regs; + + if (!regs) + return 0; + if (tsk == current && (regs->msr & MSR_FP)) + giveup_fpu(current); + + memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); + return 1; } @@ -113,7 +130,7 @@ } static void show_tsk_stack(struct task_struct *p, unsigned long sp); -static char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen); +char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen); void show_regs(struct pt_regs * regs) { @@ -300,7 +317,6 @@ unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - struct task_struct *p; unsigned long parent_tidptr = 0; unsigned long child_tidptr = 0; @@ -320,36 +336,29 @@ if (regs->msr & MSR_FP) giveup_fpu(current); - p = do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, + return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, (int *)parent_tidptr, (int *)child_tidptr); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - struct task_struct *p; - if (regs->msr & MSR_FP) giveup_fpu(current); - p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); } int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - struct task_struct *p; - if (regs->msr & MSR_FP) giveup_fpu(current); - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, @@ -404,7 +413,7 @@ * __get_free_pages() might give us a page > KERNBASE+256M which * is mapped with large ptes so we can't set up the guard page. */ - if (cpu_has_largepage()) + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) return; for (i=0; i < NR_CPUS; i++) { @@ -418,7 +427,7 @@ extern char _stext[], _etext[], __init_begin[], __init_end[]; -static char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen) +char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen) { unsigned long tb_flags; unsigned short name_len; diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/prom.c Thu Jun 19 00:45:34 2003 @@ -1120,7 +1120,7 @@ _prom->cpu = (int)(unsigned long)getprop_rval; _xPaca[_prom->cpu].active = 1; #ifdef CONFIG_SMP - RELOC(cpu_online_map) = 1 << _prom->cpu; + RELOC(cpu_online_map) = 1UL << _prom->cpu; #endif RELOC(boot_cpuid) = _prom->cpu; diff -Nru a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c --- a/arch/ppc64/kernel/ras.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/ras.c Thu Jun 19 00:45:34 2003 @@ -56,7 +56,6 @@ static void ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs); static void ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs); -void init_ras_IRQ(void); /* #define DEBUG */ @@ -64,7 +63,8 @@ * Initialize handlers for the set of interrupts caused by hardware errors * and power system events. */ -void init_ras_IRQ(void) { +static int __init init_ras_IRQ(void) +{ struct device_node *np; unsigned int *ireg, len, i; @@ -89,7 +89,10 @@ ireg++; } } + + return 1; } +__initcall(init_ras_IRQ); /* * Handle power subsystem events (EPOW). diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/setup.c Thu Jun 19 00:45:34 2003 @@ -142,9 +142,6 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - /* This should be fixed properly in kernel/resource.c */ - iomem_resource.end = MEM_SPACE_LIMIT; - #ifdef CONFIG_XMON_DEFAULT debugger = xmon; debugger_bpt = xmon_bpt; @@ -156,10 +153,10 @@ #ifdef CONFIG_PPC_ISERIES /* pSeries systems are identified in prom.c via OF. */ if ( itLpNaca.xLparInstalled == 1 ) - naca->platform = PLATFORM_ISERIES_LPAR; + systemcfg->platform = PLATFORM_ISERIES_LPAR; #endif - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init_early(); @@ -185,7 +182,7 @@ #endif } - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; register_console(&udbg_console); } @@ -193,32 +190,27 @@ printk("Starting Linux PPC64 %s\n", UTS_RELEASE); printk("-----------------------------------------------------\n"); - printk("naca = 0x%p\n", naca); -#if 0 - printk("naca->processorCount = 0x%x\n", naca->processorCount); -#endif - printk("naca->physicalMemorySize = 0x%lx\n", naca->physicalMemorySize); - printk("naca->dCacheL1LineSize = 0x%x\n", naca->dCacheL1LineSize); - printk("naca->dCacheL1LogLineSize = 0x%x\n", naca->dCacheL1LogLineSize); - printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage); - printk("naca->iCacheL1LineSize = 0x%x\n", naca->iCacheL1LineSize); - printk("naca->iCacheL1LogLineSize = 0x%x\n", naca->iCacheL1LogLineSize); - printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage); - printk("naca->pftSize = 0x%lx\n", naca->pftSize); - printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); - printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller); - printk("htab_data.htab = 0x%p\n", htab_data.htab); - printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); + printk("naca = 0x%p\n", naca); + printk("naca->pftSize = 0x%lx\n", naca->pftSize); + printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); + printk("naca->interrupt_controller = 0x%ld\n", naca->interrupt_controller); + printk("systemcfg = 0x%p\n", systemcfg); + printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); + printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); + printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize); + printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize); + printk("htab_data.htab = 0x%p\n", htab_data.htab); + printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); printk("-----------------------------------------------------\n"); - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { finish_device_tree(); chrp_init(r3, r4, r5, r6, r7); } mm_init_ppc64(); - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init(); @@ -264,7 +256,7 @@ return 0; } - if (!(cpu_online_map & (1<platform != PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform != PLATFORM_ISERIES_LPAR) { struct device_node *cpu_node; int *fp; @@ -373,16 +365,15 @@ cmd_line[0] = 0; #ifdef CONFIG_CMDLINE - strcpy(cmd_line, CONFIG_CMDLINE); + strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); #endif /* CONFIG_CMDLINE */ chosen = find_devices("chosen"); if (chosen != NULL) { p = get_property(chosen, "bootargs", NULL); if (p != NULL && p[0] != 0) - strncpy(cmd_line, p, sizeof(cmd_line)); + strlcpy(cmd_line, p, sizeof(cmd_line)); } - cmd_line[sizeof(cmd_line) - 1] = 0; /* Look for mem= option on command line */ if (strstr(cmd_line, "mem=")) { @@ -516,8 +507,8 @@ * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - dcache_bsize = naca->dCacheL1LineSize; - icache_bsize = naca->iCacheL1LineSize; + dcache_bsize = systemcfg->dCacheL1LineSize; + icache_bsize = systemcfg->iCacheL1LineSize; /* reboot on panic */ panic_timeout = 180; @@ -593,7 +584,7 @@ /* The parameter is the number of processors to share in processing lp events */ unsigned long i; unsigned long val = simple_strtoul( str, NULL, 0 ); - if ( ( val > 0 ) && ( val <= MAX_PACAS ) ) { + if ( ( val > 0 ) && ( val <= NR_CPUS ) ) { for ( i=1; isighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) - /* - * If a signal handler needs to be called, - * do_signal() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal() doesn't touch - * R3, so it's still set to -EINTR (see above). - */ - return regs->gpr[3]; - } -} - -long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6, - int p7, struct pt_regs *regs) +long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, + int p6, int p7, struct pt_regs *regs) { sigset_t saveset, newset; @@ -170,339 +109,232 @@ return do_sigaltstack(uss, uoss, regs->gpr[1]); } -long sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) + +/* + * Set up the sigcontext for the signal frame. + */ + +static int +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + int signr, sigset_t *set, unsigned long handler) { - struct k_sigaction new_ka, old_ka; - int ret; + int err = 0; - if (act) { - old_sigset_t mask; + if (regs->msr & MSR_FP) + giveup_fpu(current); - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } + current->thread.saved_msr = regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->msr = current->thread.saved_msr | current->thread.fpexc_mode; + current->thread.saved_softe = regs->softe; + + err |= __put_user(&sc->gp_regs, &sc->regs); + err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); + err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); + err |= __put_user(signr, &sc->signal); + err |= __put_user(handler, &sc->handler); + if (set != NULL) + err |= __put_user(set->sig[0], &sc->oldmask); - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } + regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + current->thread.fpscr = 0; - return ret; + return err; } /* - * When we have rt signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one rt_sigframe struct (siginfo + ucontext) - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * + * Restore the sigcontext from the signal frame. */ -int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) +static int +restore_sigcontext(struct pt_regs *regs, sigset_t *set, struct sigcontext *sc) { - struct rt_sigframe *rt_sf; - struct sigcontext sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ - sigset_t set; - stack_t st; + unsigned int err = 0; - rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) - || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set)) - || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st))) - goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); if (regs->msr & MSR_FP) giveup_fpu(current); - /* restore registers - - * sigctx is initialized to point to the - * preamble frame (where registers are stored) - * see handle_signal() - */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) - goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - /* This function sets back the stack flags into - the current task structure. */ - sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); - - return regs->result; + err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE); + err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); + current->thread.fpexc_mode = regs->msr & (MSR_FE0 | MSR_FE1); + if (set != NULL) + err |= __get_user(set->sig[0], &sc->oldmask); + + /* Don't allow the signal handler to change these modulo FE{0,1} */ + regs->msr = current->thread.saved_msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->softe = current->thread.saved_softe; -badframe: - do_exit(SIGSEGV); + return err; } -static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, - signed long newsp) +/* + * Allocate space for the signal frame + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { - struct rt_sigframe *rt_sf = (struct rt_sigframe *)newsp; - /* Handler is *really* a pointer to the function descriptor for - * the signal routine. The first entry in the function - * descriptor is the entry address of signal and the second - * entry is the TOC value we need to use. - */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + unsigned long newsp; - /* Set up preamble frame */ - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_rt_sigreturn */ - || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ - - /* Retrieve rt_sigframe from stack and - set up registers for signal handler - */ - newsp -= __SIGNAL_FRAMESIZE; + /* Default to using normal stack */ + newsp = regs->gpr[1]; - if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { - goto badframe; + if (ka->sa.sa_flags & SA_ONSTACK) { + if (! on_sig_stack(regs->gpr[1])) + newsp = (current->sas_ss_sp + current->sas_ss_size); } - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr->entry) - || get_user(regs->gpr[2], &funct_desc_ptr->toc) - || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal) - || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo) - || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc)) - goto badframe; + return (void *)((newsp - frame_size) & -8ul); +} - regs->gpr[1] = newsp; - regs->gpr[6] = (unsigned long)rt_sf; - regs->link = (unsigned long)frame->tramp; +static int +setup_trampoline(unsigned int syscall, unsigned int *tramp) +{ + int i, err = 0; - return; + /* addi r1, r1, __SIGNAL_FRAMESIZE # Pop the dummy stackframe */ + err |= __put_user(0x38210000UL | (__SIGNAL_FRAMESIZE & 0xffff), &tramp[0]); + /* li r0, __NR_[rt_]sigreturn| */ + err |= __put_user(0x38000000UL | (syscall & 0xffff), &tramp[1]); + /* sc */ + err |= __put_user(0x44000002UL, &tramp[2]); + + /* Minimal traceback info */ + for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++) + err |= __put_user(0, &tramp[i]); + + if (!err) + flush_icache_range((unsigned long) &tramp[0], + (unsigned long) &tramp[TRAMP_SIZE]); -badframe: -#if DEBUG_SIG - printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", - regs, frame, newsp); -#endif - do_exit(SIGSEGV); + return err; } /* * Do a signal return; undo the signal stack. */ -long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) -{ - struct sigcontext *sc, sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ + +int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, unsigned long r8, + struct pt_regs *regs) +{ + struct ucontext *uc = (struct ucontext *)regs->gpr[1]; sigset_t set; + stack_t st; - sc = (struct sigcontext *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + if (verify_area(VERIFY_READ, uc, sizeof(*uc))) goto badframe; - set.sig[0] = sigctx.oldmask; -#if _NSIG_WORDS > 1 - set.sig[1] = sigctx._unused[3]; -#endif + if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (regs->msr & MSR_FP) - giveup_fpu(current); - /* restore registers */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) + if (restore_sigcontext(regs, NULL, &uc->uc_mcontext)) goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) + if (__copy_from_user(&st, &uc->uc_stack, sizeof(st))) goto badframe; + /* This function sets back the stack flags into + the current task structure. */ + sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); return regs->result; badframe: +#if DEBUG_SIG + printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", + regs, uc, &uc->uc_mcontext); +#endif do_exit(SIGSEGV); -} +} -/* - * Set up a signal frame. - */ -static void setup_frame(struct pt_regs *regs, struct sigregs *frame, - unsigned long newsp) +static void +setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) { - /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + func_descr_t *funct_desc_ptr; + struct rt_sigframe *frame; + unsigned long newsp = 0; + int err = 0; - struct sigcontext *sc = (struct sigcontext *)newsp; - - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_sigreturn */ - || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ + frame = get_sigframe(ka, regs, sizeof(*frame)); - newsp -= __SIGNAL_FRAMESIZE; - if (get_user(temp_ptr, &sc->handler)) + if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; - - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr ->entry) - || get_user(regs->gpr[2],&funct_desc_ptr->toc) - || get_user(regs->gpr[3], &sc->signal)) - goto badframe; + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + if (err) + goto badframe; + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->gpr[1]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, + (unsigned long)ka->sa.sa_handler); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto badframe; + + /* Set up to return from userspace. */ + err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); + if (err) + goto badframe; + + funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; + + /* Allocate a dummy caller frame for the signal handler. */ + newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; + err |= put_user(0, (unsigned long *)newsp); + + /* Set up "regs" so we "return" to the signal handler. */ + err |= get_user(regs->nip, &funct_desc_ptr->entry); + regs->link = (unsigned long) &frame->tramp[0]; regs->gpr[1] = newsp; - regs->gpr[4] = (unsigned long)sc; - regs->link = (unsigned long)frame->tramp; + err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); + regs->gpr[3] = signr; + if (ka->sa.sa_flags & SA_SIGINFO) { + err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo); + err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc); + regs->gpr[6] = (unsigned long) frame; + } else { + regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; + } + if (err) + goto badframe; return; badframe: #if DEBUG_SIG - printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", + printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif do_exit(SIGSEGV); } + /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned long *newspp, unsigned long frame) +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - struct sigcontext *sc; - struct rt_sigframe *rt_sf; - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - - if (regs->trap == 0x0C00 /* System Call! */ - && ((int)regs->result == -ERESTARTNOHAND || - (int)regs->result == -ERESTART_RESTARTBLOCK || - ((int)regs->result == -ERESTARTSYS && - !(ka->sa.sa_flags & SA_RESTART)))) { - if ((int)regs->result == -ERESTART_RESTARTBLOCK) - current_thread_info()->restart_block.fn - = do_no_restart_syscall; - regs->result = -EINTR; - } - /* Set up Signal Frame */ - if (ka->sa.sa_flags & SA_SIGINFO) { - /* Put a Real Time Context onto stack */ - *newspp -= sizeof(*rt_sf); - rt_sf = (struct rt_sigframe *)*newspp; - if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, - &rt_sf->uc.uc_mcontext.handler) - || __put_user(&rt_sf->info, &rt_sf->pinfo) - || __put_user(&rt_sf->uc, &rt_sf->puc) - /* Put the siginfo */ - || copy_siginfo_to_user(&rt_sf->info, info) - /* Create the ucontext */ - || __put_user(0, &rt_sf->uc.uc_flags) - || __put_user(0, &rt_sf->uc.uc_link) - || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) - || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_sf->uc.uc_stack.ss_flags) - || __put_user(current->sas_ss_size, - &rt_sf->uc.uc_stack.ss_size) - || __copy_to_user(&rt_sf->uc.uc_sigmask, - oldset, sizeof(*oldset)) - /* mcontext.regs points to preamble register frame */ - || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) - || __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) - goto badframe; - } else { - /* Put a sigcontext on the stack */ - *newspp -= sizeof(*sc); - sc = (struct sigcontext *)*newspp; - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, &sc->handler) - || __put_user(oldset->sig[0], &sc->oldmask) -#if _NSIG_WORDS > 1 - || __put_user(oldset->sig[1], &sc->_unused[3]) -#endif - || __put_user((struct pt_regs *)frame, &sc->regs) - || __put_user(sig, &sc->signal)) - goto badframe; - } + setup_rt_frame(sig, ka, info, oldset, regs); if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; @@ -515,14 +347,40 @@ spin_unlock_irq(¤t->sighand->siglock); } return; +} -badframe: -#if DEBUG_SIG - printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n", - regs, frame, *newspp); - printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset); -#endif - do_exit(SIGSEGV); +static inline void +syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +{ + switch ((int)regs->result) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = do_no_restart_syscall; + /* fallthrough */ + case -ERESTARTNOHAND: + /* ERESTARTNOHAND means that the syscall should only be + * restarted if there was no handler for the signal, and since + * we only get here if there is a handler, we dont restart. + */ + regs->result = -EINTR; + break; + case -ERESTARTSYS: + /* ERESTARTSYS means to restart the syscall if there is no + * handler or the handler was registered with SA_RESTART + */ + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->result = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* ERESTARTNOINTR means that the syscall should be + * called again after the signal handler returns. + */ + regs->gpr[3] = regs->orig_gpr3; + regs->nip -= 4; + regs->result = 0; + break; + } } /* @@ -530,13 +388,9 @@ * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); - int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; - unsigned long frame, newsp; int signr; /* @@ -549,20 +403,15 @@ if (!oldset) oldset = ¤t->blocked; - newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - ka = ¤t->sighand->action[signr-1]; - if ((ka->sa.sa_flags & SA_ONSTACK) - && (!on_sig_stack(regs->gpr[1]))) - newsp = (current->sas_ss_sp + current->sas_ss_size); - else - newsp = regs->gpr[1]; - newsp = frame = newsp - sizeof(struct sigregs); + struct k_sigaction *ka = ¤t->sighand->action[signr-1]; /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs, &newsp, frame); + if (regs->trap == 0x0C00) + syscall_restart(regs, ka); + handle_signal(signr, ka, &info, oldset, regs); + return 1; } if (regs->trap == 0x0C00) { /* System Call! */ @@ -579,13 +428,8 @@ } } - if (newsp == frame) - return 0; /* no signals delivered */ - - /* Invoke correct stack setup routine */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(regs, (struct sigregs *)frame, newsp); - else - setup_frame(regs, (struct sigregs *)frame, newsp); - return 1; + return 0; } + + + diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/signal32.c Thu Jun 19 00:45:34 2003 @@ -529,10 +529,6 @@ return ret; } - -extern long sys_rt_sigprocmask(int how, sigset_t *set, - sigset_t *oset, size_t sigsetsize); - /* * Note: it is necessary to treat how as an unsigned int, with the * corresponding cast to a signed int to insure that the proper @@ -579,10 +575,6 @@ return 0; } - -extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); - - long sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize) { sigset_t s; @@ -649,11 +641,6 @@ return err; } - -extern long sys_rt_sigtimedwait(const sigset_t *uthese, - siginfo_t *uinfo, const struct timespec *uts, - size_t sigsetsize); - long sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo, struct compat_timespec *uts, compat_size_t sigsetsize) { @@ -724,9 +711,6 @@ return d; } - -extern long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); - /* * Note: it is necessary to treat pid and sig as unsigned ints, with the * corresponding cast to a signed int to insure that the proper conversion @@ -751,8 +735,6 @@ set_fs (old_fs); return ret; } - -extern int do_signal(sigset_t *oldset, struct pt_regs *regs); int sys32_rt_sigsuspend(compat_sigset_t* unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs) diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/smp.c Thu Jun 19 00:45:34 2003 @@ -46,8 +46,10 @@ #include #include "open_pic.h" #include +#include +#include -int smp_threads_ready = 0; +int smp_threads_ready; unsigned long cache_decay_ticks; /* initialised so it doesn't end up in bss */ @@ -63,18 +65,6 @@ void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); -void xics_setup_cpu(void); -void xics_cause_IPI(int cpu); - -/* - * XICS only has a single IPI, so encode the messages per CPU - */ -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; - -struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; - #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) static inline void set_tb(unsigned int upper, unsigned int lower) @@ -124,7 +114,7 @@ struct ItLpPaca * lpPaca; np = 0; - for (i=0; i < MAX_PACAS; ++i) { + for (i=0; i < NR_CPUS; ++i) { lpPaca = paca[i].xLpPacaPtr; if ( lpPaca->xDynProcStatus < 2 ) { ++np; @@ -139,7 +129,7 @@ unsigned np = 0; struct ItLpPaca *lpPaca; - for (i=0; i < MAX_PACAS; ++i) { + for (i=0; i < NR_CPUS; ++i) { lpPaca = paca[i].xLpPacaPtr; if (lpPaca->xDynProcStatus < 2) { paca[i].active = 1; @@ -155,7 +145,7 @@ struct ItLpPaca * lpPaca; /* Verify we have a Paca for processor nr */ if ( ( nr <= 0 ) || - ( nr >= MAX_PACAS ) ) + ( nr >= NR_CPUS ) ) return; /* Verify that our partition has a processor nr */ lpPaca = paca[nr].xLpPacaPtr; @@ -189,7 +179,7 @@ smp_ops->kick_cpu = smp_iSeries_kick_cpu; smp_ops->setup_cpu = smp_iSeries_setup_cpu; #warning fix for iseries - naca->processorCount = smp_iSeries_numProcs(); + systemcfg->processorCount = smp_iSeries_numProcs(); } #endif @@ -239,7 +229,7 @@ { /* Verify we have a Paca for processor nr */ if ( ( nr <= 0 ) || - ( nr >= MAX_PACAS ) ) + ( nr >= NR_CPUS ) ) return; /* The information for processor bringup must @@ -353,7 +343,7 @@ smp_ops->probe = smp_xics_probe; } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { smp_ops->give_timebase = pSeries_give_timebase; smp_ops->take_timebase = pSeries_take_timebase; } @@ -403,17 +393,6 @@ smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0); } -/* - * this function sends a reschedule IPI to all (other) CPUs. - * This should only be used if some 'global' task became runnable, - * such as a RT task, that must be handled now. The first CPU - * that manages to grab the task will run it. - */ -void smp_send_reschedule_all(void) -{ - smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_RESCHEDULE, 0, 0); -} - #ifdef CONFIG_XMON void smp_send_xmon_break(int cpu) { @@ -605,7 +584,7 @@ paca[cpu].prof_multiplier = 1; paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock; - if (!cpu_has_slb()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { void *tmp; /* maximum of 48 CPUs on machines with a segment table */ @@ -621,10 +600,11 @@ /* create a process for the processor */ /* only regs.msr is actually used, and 0 is OK for it */ memset(®s, 0, sizeof(struct pt_regs)); - p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); + wake_up_forked_process(p); init_idle(p, cpu); unhash_process(p); diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Thu Jun 19 00:45:34 2003 @@ -1829,7 +1829,7 @@ err = do_sys32_shmctl(first, second, (void *)AA(ptr)); break; default: - err = -ENOSYS; + err = -EINVAL; break; } return err; diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/syscalls.c Thu Jun 19 00:45:34 2003 @@ -50,11 +50,6 @@ { } -int sys_ioperm(unsigned long from, unsigned long num, int on) -{ - return -EIO; -} - /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/traps.c Thu Jun 19 00:45:34 2003 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -55,14 +56,12 @@ * Trap & Exception support */ -/* Should we panic on bad kernel exceptions or try to recover */ -#undef PANIC_ON_ERROR - static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char *str, struct pt_regs *regs, long err) { static int die_counter; + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -71,11 +70,16 @@ bust_spinlocks(0); spin_unlock_irq(&die_lock); -#ifdef PANIC_ON_ERROR - panic(str); -#else + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) { + printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(5 * HZ); + panic("Fatal exception"); + } do_exit(SIGSEGV); -#endif } static void @@ -139,15 +143,13 @@ #ifdef CONFIG_DEBUG_KERNEL if (debugger) debugger(regs); + else #endif + panic("System Reset"); -#ifdef PANIC_ON_ERROR - panic("System Reset"); -#else /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) panic("Unrecoverable System Reset"); -#endif /* What should we do here? We could issue a shutdown or hard reset. */ } @@ -305,6 +307,56 @@ _exception(SIGFPE, &info, regs); } +/* + * Look through the list of trap instructions that are used for BUG(), + * BUG_ON() and WARN_ON() and see if we hit one. At this point we know + * that the exception was caused by a trap instruction of some kind. + * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0 + * otherwise. + */ +extern struct bug_entry __start___bug_table[], __stop___bug_table[]; + +#ifndef CONFIG_MODULES +#define module_find_bug(x) NULL +#endif + +static struct bug_entry *find_bug(unsigned long bugaddr) +{ + struct bug_entry *bug; + + for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) + if (bugaddr == bug->bug_addr) + return bug; + return module_find_bug(bugaddr); +} + +int +check_bug_trap(struct pt_regs *regs) +{ + struct bug_entry *bug; + unsigned long addr; + + if (regs->msr & MSR_PR) + return 0; /* not in kernel */ + addr = regs->nip; /* address of trap instruction */ + if (addr < PAGE_OFFSET) + return 0; + bug = find_bug(regs->nip); + if (bug == NULL) + return 0; + if (bug->line & BUG_WARNING_TRAP) { + /* this is a WARN_ON rather than BUG/BUG_ON */ + printk(KERN_ERR "Badness in %s at %s:%d\n", + bug->function, bug->file, + bug->line & ~BUG_WARNING_TRAP); + dump_stack(); + return 1; + } + printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", + bug->function, bug->file, bug->line); + return 0; +} + void ProgramCheckException(struct pt_regs *regs) { @@ -329,6 +381,10 @@ if (debugger_bpt && debugger_bpt(regs)) return; #endif + if (check_bug_trap(regs)) { + regs->nip += 4; + return; + } info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; @@ -343,6 +399,14 @@ info.si_addr = (void *)regs->nip; _exception(SIGILL, &info, regs); } +} + +void +KernelFPUnavailableException(struct pt_regs *regs) +{ + printk("Illegal floating point used in kernel (task=0x%p, " + "pc=0x%016lx, trap=0x%lx)\n", current, regs->nip, regs->trap); + panic("Unrecoverable FP Unavailable Exception in Kernel"); } void diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/kernel/xics.c Thu Jun 19 00:45:34 2003 @@ -1,5 +1,5 @@ /* - * arch/ppc/kernel/xics.c + * arch/ppc64/kernel/xics.c * * Copyright 2000 IBM Corporation. * @@ -22,11 +22,13 @@ #include #include #include -#include "i8259.h" #include #include +#include #include +#include "i8259.h" + void xics_enable_irq(u_int irq); void xics_disable_irq(u_int irq); void xics_mask_and_ack_irq(u_int irq); @@ -61,33 +63,39 @@ /* Want a priority other than 0. Various HW issues require this. */ #define DEFAULT_PRIORITY 5 +/* + * Mark IPIs as higher priority so we can take them inside interrupts that + * arent marked SA_INTERRUPT + */ +#define IPI_PRIORITY 4 + struct xics_ipl { union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } xirr_poll; union { u32 word; - u8 bytes[4]; + u8 bytes[4]; } xirr; - u32 dummy; + u32 dummy; union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } qirr; }; -struct xics_info { - volatile struct xics_ipl * per_cpu[NR_CPUS]; -}; +static struct xics_ipl *xics_per_cpu[NR_CPUS]; -struct xics_info xics_info; +static int xics_irq_8259_cascade = 0; +static int xics_irq_8259_cascade_real = 0; +static unsigned int default_server = 0xFF; +static unsigned int default_distrib_server = 0; -unsigned long long intr_base = 0; -int xics_irq_8259_cascade = 0; -int xics_irq_8259_cascade_real = 0; -unsigned int default_server = 0xFF; -unsigned int default_distrib_server = 0; +/* + * XICS only has a single IPI, so encode the messages per CPU + */ +struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; /* RTAS service tokens */ int ibm_get_xive; @@ -95,11 +103,6 @@ int ibm_int_on; int ibm_int_off; -struct xics_interrupt_node { - unsigned long long addr; - unsigned long long size; -} inodes[NR_CPUS*2]; - typedef struct { int (*xirr_info_get)(int cpu); void (*xirr_info_set)(int cpu, int val); @@ -108,24 +111,26 @@ } xics_ops; +/* SMP */ + static int pSeries_xirr_info_get(int n_cpu) { - return (xics_info.per_cpu[n_cpu]->xirr.word); + return xics_per_cpu[n_cpu]->xirr.word; } static void pSeries_xirr_info_set(int n_cpu, int value) { - xics_info.per_cpu[n_cpu]->xirr.word = value; + xics_per_cpu[n_cpu]->xirr.word = value; } static void pSeries_cppr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->xirr.bytes[0] = value; + xics_per_cpu[n_cpu]->xirr.bytes[0] = value; } -static void pSeries_qirr_info(int n_cpu , u8 value) +static void pSeries_qirr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->qirr.bytes[0] = value; + xics_per_cpu[n_cpu]->qirr.bytes[0] = value; } static xics_ops pSeries_ops = { @@ -136,113 +141,174 @@ }; static xics_ops *ops = &pSeries_ops; -extern xics_ops pSeriesLP_ops; -void -xics_enable_irq( - u_int virq - ) +/* LPAR */ + +static inline long plpar_eoi(unsigned long xirr) { - u_int irq; - unsigned long status; - long call_status; + return plpar_hcall_norets(H_EOI, xirr); +} + +static inline long plpar_cppr(unsigned long cppr) +{ + return plpar_hcall_norets(H_CPPR, cppr); +} + +static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr) +{ + return plpar_hcall_norets(H_IPI, servernum, mfrr); +} + +static inline long plpar_xirr(unsigned long *xirr_ret) +{ + unsigned long dummy; + return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); +} + +static int pSeriesLP_xirr_info_get(int n_cpu) +{ + unsigned long lpar_rc; + unsigned long return_value; + + lpar_rc = plpar_xirr(&return_value); + if (lpar_rc != H_Success) + panic(" bad return code xirr - rc = %lx \n", lpar_rc); + return (int)return_value; +} + +static void pSeriesLP_xirr_info_set(int n_cpu, int value) +{ + unsigned long lpar_rc; + unsigned long val64 = value & 0xffffffff; + + lpar_rc = plpar_eoi(val64); + if (lpar_rc != H_Success) + panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc, + val64); +} + +static void pSeriesLP_cppr_info(int n_cpu, u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_cppr(value); + if (lpar_rc != H_Success) + panic("bad return code cppr - rc = %lx\n", lpar_rc); +} + +static void pSeriesLP_qirr_info(int n_cpu , u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_ipi(n_cpu, value); + if (lpar_rc != H_Success) + panic("bad return code qirr - rc = %lx\n", lpar_rc); +} + +xics_ops pSeriesLP_ops = { + pSeriesLP_xirr_info_get, + pSeriesLP_xirr_info_set, + pSeriesLP_cppr_info, + pSeriesLP_qirr_info +}; + +void xics_enable_irq(u_int virq) +{ + u_int irq; + long call_status; + unsigned int server; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); if (irq == XICS_IPI) return; + #ifdef CONFIG_IRQ_ALL_CPUS - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, smp_threads_ready ? default_distrib_server : default_server, DEFAULT_PRIORITY); + if (smp_threads_ready) + server = default_distrib_server; + else + server = default_server; #else - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, default_server, DEFAULT_PRIORITY); + server = default_server; #endif - if( call_status != 0 ) { - printk("xics_enable_irq: irq=%x: rtas_call failed; retn=%lx, status=%lx\n", - irq, call_status, status); + + call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, + DEFAULT_PRIORITY); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_set_xive returned %lx\n", + irq, call_status); return; } + /* Now unmask the interrupt (often a no-op) */ - call_status = rtas_call(ibm_int_on, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq on: irq=%x: rtas_call failed, retn=%lx\n", + call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_int_on returned %lx\n", irq, call_status); return; } } -void -xics_disable_irq( - u_int virq - ) -{ - u_int irq; - unsigned long status; - long call_status; +void xics_disable_irq(u_int virq) +{ + u_int irq; + long call_status; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); - call_status = rtas_call(ibm_int_off, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq: irq=%x: rtas_call failed, retn=%lx\n", + if (irq == XICS_IPI) + return; + + call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_disable_irq: irq=%x: ibm_int_off returned %lx\n", irq, call_status); return; } } -void -xics_end_irq( - u_int irq - ) +void xics_end_irq(u_int irq) { int cpu = smp_processor_id(); - ops->cppr_info(cpu, 0); /* actually the value overwritten by ack */ - iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); iosync(); + ops->xirr_info_set(cpu, ((0xff<<24) | + (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); } -void -xics_mask_and_ack_irq(u_int irq) +void xics_mask_and_ack_irq(u_int irq) { int cpu = smp_processor_id(); - if( irq < XICS_IRQ_OFFSET ) { + if (irq < XICS_IRQ_OFFSET) { i8259_pic.ack(irq); iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | xics_irq_8259_cascade_real)); - iosync(); - } - else { - ops->cppr_info(cpu, 0xff); + ops->xirr_info_set(cpu, ((0xff<<24) | + xics_irq_8259_cascade_real)); iosync(); } } -int -xics_get_irq(struct pt_regs *regs) +int xics_get_irq(struct pt_regs *regs) { - u_int cpu = smp_processor_id(); - u_int vec; + u_int cpu = smp_processor_id(); + u_int vec; int irq; vec = ops->xirr_info_get(cpu); /* (vec >> 24) == old priority */ vec &= 0x00ffffff; + /* for sanity, this had better be < NR_IRQS - 16 */ - if( vec == xics_irq_8259_cascade_real ) { + if (vec == xics_irq_8259_cascade_real) { irq = i8259_irq(cpu); - if(irq == -1) { + if (irq == -1) { /* Spurious cascaded interrupt. Still must ack xics */ xics_end_irq(XICS_IRQ_OFFSET + xics_irq_8259_cascade); irq = -1; } - } else if( vec == XICS_IRQ_SPURIOUS ) { + } else if (vec == XICS_IRQ_SPURIOUS) { irq = -1; } else { irq = real_irq_to_virt(vec) + XICS_IRQ_OFFSET; @@ -250,45 +316,47 @@ return irq; } -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; +#ifdef CONFIG_SMP extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; -#ifdef CONFIG_SMP -void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); ops->qirr_info(cpu, 0xff); while (xics_ipi_message[cpu].value) { - if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_CALL_FUNCTION, regs); } - if (test_and_clear_bit(PPC_MSG_RESCHEDULE, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_RESCHEDULE, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_RESCHEDULE, regs); } #if 0 - if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_MIGRATE_TASK, regs); } #endif #ifdef CONFIG_XMON - if (test_and_clear_bit(PPC_MSG_XMON_BREAK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_XMON_BREAK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_XMON_BREAK, regs); } #endif } + return IRQ_HANDLED; } void xics_cause_IPI(int cpu) { - ops->qirr_info(cpu,0) ; + ops->qirr_info(cpu, IPI_PRIORITY); } void xics_setup_cpu(void) @@ -298,15 +366,20 @@ ops->cppr_info(cpu, 0xff); iosync(); } + #endif /* CONFIG_SMP */ -void -xics_init_IRQ( void ) +void xics_init_IRQ(void) { int i; unsigned long intr_size = 0; struct device_node *np; uint *ireg, ilen, indx=0; + unsigned long intr_base = 0; + struct xics_interrupt_node { + unsigned long long addr; + unsigned long long size; + } inodes[NR_CPUS*2]; ppc64_boot_msg(0x20, "XICS Init"); @@ -386,23 +459,24 @@ xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { #ifdef CONFIG_SMP for (i = 0; i < NR_CPUS; ++i) { if (!cpu_possible(i)) continue; - xics_info.per_cpu[i] = - __ioremap((ulong)inodes[i].addr, - (ulong)inodes[i].size, _PAGE_NO_CACHE); + xics_per_cpu[i] = __ioremap((ulong)inodes[i].addr, + (ulong)inodes[i].size, + _PAGE_NO_CACHE); } #else - xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); + xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, + _PAGE_NO_CACHE); #endif /* CONFIG_SMP */ #ifdef CONFIG_PPC_PSERIES /* actually iSeries does not use any of xics...but it has link dependencies * for now, except this new one... */ - } else if (naca->platform == PLATFORM_PSERIES_LPAR) { + } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; #endif } @@ -417,8 +491,8 @@ ops->cppr_info(boot_cpuid, 0xff); iosync(); if (xics_irq_8259_cascade != -1) { - if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action, - 0, "8259 cascade", 0)) + if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, + no_action, 0, "8259 cascade", 0)) printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); i8259_init(); } diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/mm/init.c Thu Jun 19 00:45:34 2003 @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_INITRD #include /* for initrd_* */ #endif @@ -58,6 +59,7 @@ #include #include #include +#include #include @@ -95,7 +97,7 @@ /* This is declared as we are using the more or less generic * include/asm-ppc64/tlb.h file -- tgall */ -struct mmu_gather mmu_gathers[NR_CPUS]; +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); void show_mem(void) { @@ -510,6 +512,37 @@ } #endif +static struct kcore_list kcore_vmem; + +static int __init setup_kcore(void) +{ + int i; + + for (i=0; i < lmb.memory.cnt; i++) { + unsigned long physbase, size; + unsigned long type = lmb.memory.region[i].type; + struct kcore_list *kcore_mem; + + if (type != LMB_MEMORY_AREA) + continue; + + physbase = lmb.memory.region[i].physbase; + size = lmb.memory.region[i].size; + + /* GFP_ATOMIC to avoid might_sleep warnings during boot */ + kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC); + if (!kcore_mem) + panic("mem_init: kmalloc failed\n"); + + kclist_add(kcore_mem, __va(physbase), size); + } + + kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); + + return 0; +} +module_init(setup_kcore); + void initialize_paca_hardware_interrupt_stack(void); void __init mem_init(void) @@ -668,7 +701,7 @@ int local = 0; /* handle i-cache coherency */ - if (!cpu_has_noexecute()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_NOEXECUTE)) { unsigned long pfn = pte_pfn(pte); if (pfn_valid(pfn)) { struct page *page = pfn_to_page(pfn); diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c Thu Jun 19 00:45:34 2003 +++ b/arch/ppc64/mm/numa.c Thu Jun 19 00:45:34 2003 @@ -24,11 +24,22 @@ int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] = -1}; int numa_memory_lookup_table[MAX_MEMORY >> MEMORY_INCREMENT_SHIFT] = { [ 0 ... ((MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1)] = -1}; -int numa_node_exists[MAX_NUMNODES]; +unsigned long numa_cpumask_lookup_table[MAX_NUMNODES]; +int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0}; struct pglist_data node_data[MAX_NUMNODES]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; +static inline void map_cpu_to_node(int cpu, int node) +{ + dbg("cpu %d maps to domain %d\n", cpu, node); + numa_cpu_lookup_table[cpu] = node; + if (!(numa_cpumask_lookup_table[node] & 1UL << cpu)) { + numa_cpumask_lookup_table[node] |= 1UL << cpu; + nr_cpus_in_node[node]++; + } +} + static int __init parse_numa_properties(void) { struct device_node *cpu; @@ -88,9 +99,7 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_cpu_lookup_table[cpu_nr] = numa_domain; - - dbg("cpu %d maps to domain %d\n", cpu_nr, numa_domain); + map_cpu_to_node(cpu_nr, numa_domain); } for (memory = find_type_devices("memory"); memory; @@ -135,7 +144,7 @@ /* FIXME */ if (numa_domain == 0xffff) { - dbg("cpu has no numa doman\n"); + dbg("memory has no numa doman\n"); numa_domain = 0; } @@ -145,7 +154,28 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_node_exists[numa_domain] = 1; + /* + * For backwards compatibility, OF splits the first node + * into two regions (the first being 0-4GB). Check for + * this simple case and complain if there is a gap in + * memory + */ + if (node_data[numa_domain].node_size) { + unsigned long shouldstart = + node_data[numa_domain].node_start_pfn + + node_data[numa_domain].node_size; + if (shouldstart != (start / PAGE_SIZE)) { + printk(KERN_ERR "Hole in node, disabling " + "region start %lx length %lx\n", + start, size); + continue; + } + node_data[numa_domain].node_size += size / PAGE_SIZE; + } else { + node_data[numa_domain].node_start_pfn = + start / PAGE_SIZE; + node_data[numa_domain].node_size = size / PAGE_SIZE; + } for (i = start ; i < (start+size); i += MEMORY_INCREMENT) numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = @@ -164,6 +194,20 @@ return 0; } +void setup_nonnuma(void) +{ + unsigned long i; + + for (i = 0; i < NR_CPUS; i++) + map_cpu_to_node(i, 0); + + node_data[0].node_start_pfn = 0; + node_data[0].node_size = lmb_end_of_DRAM() / PAGE_SIZE; + + for (i = 0 ; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) + numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0; +} + void __init do_init_bootmem(void) { int nid; @@ -171,32 +215,21 @@ min_low_pfn = 0; max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; - /* XXX FIXME: support machines without associativity information */ if (parse_numa_properties()) - BUG(); + setup_nonnuma(); for (nid = 0; nid < numnodes; nid++) { - unsigned long start, end; unsigned long start_paddr, end_paddr; int i; unsigned long bootmem_paddr; unsigned long bootmap_pages; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; - /* Find start and end of this zone */ - start = 0; - while (numa_memory_lookup_table[start] != nid) - start++; - - end = (MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1; - while (numa_memory_lookup_table[end] != nid) - end--; - end++; - - start_paddr = start << MEMORY_INCREMENT_SHIFT; - end_paddr = end << MEMORY_INCREMENT_SHIFT; + start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE; + end_paddr = start_paddr + + (node_data[nid].node_size * PAGE_SIZE); dbg("node %d\n", nid); dbg("start_paddr = %lx\n", start_paddr); @@ -204,7 +237,7 @@ NODE_DATA(nid)->bdata = &plat_node_bdata[nid]; - bootmap_pages = bootmem_bootmap_pages(end_paddr - start_paddr); + bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT); dbg("bootmap_pages = %lx\n", bootmap_pages); bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT, @@ -278,7 +311,7 @@ unsigned long start_pfn; unsigned long end_pfn; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT; diff -Nru a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c --- a/arch/sparc64/kernel/module.c Thu Jun 19 00:45:34 2003 +++ b/arch/sparc64/kernel/module.c Thu Jun 19 00:45:34 2003 @@ -138,7 +138,9 @@ /* Free memory returned from module_core_alloc/module_init_alloc */ void module_free(struct module *mod, void *module_region) { + write_lock(&vmlist_lock); module_unmap(module_region); + write_unlock(&vmlist_lock); /* FIXME: If module_region == mod->init_region, trim exception table entries. */ } diff -Nru a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c --- a/arch/x86_64/kernel/module.c Thu Jun 19 00:45:34 2003 +++ b/arch/x86_64/kernel/module.c Thu Jun 19 00:45:34 2003 @@ -48,7 +48,6 @@ for (prevp = &mod_vmlist ; (map = *prevp) ; prevp = &map->next) { if ((unsigned long)map->addr == addr) { *prevp = map->next; - write_unlock(&vmlist_lock); goto found; } } @@ -57,6 +56,7 @@ return; found: unmap_vm_area(map); + write_unlock(&vmlist_lock); if (map->pages) { for (i = 0; i < map->nr_pages; i++) if (map->pages[i]) diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Thu Jun 19 00:45:34 2003 +++ b/drivers/acpi/osl.c Thu Jun 19 00:45:34 2003 @@ -252,7 +252,14 @@ irq = acpi_fadt.sci_int; #ifdef CONFIG_IA64 - irq = gsi_to_vector(irq); + int vector; + + vector = acpi_irq_to_vector(irq); + if (vector < 0) { + printk(KERN_ERR PREFIX "SCI (IRQ%d) not registerd\n", irq); + return AE_OK; + } + irq = vector; #endif acpi_irq_irq = irq; acpi_irq_handler = handler; @@ -270,7 +277,7 @@ { if (acpi_irq_handler) { #ifdef CONFIG_IA64 - irq = gsi_to_vector(irq); + irq = acpi_irq_to_vector(irq); #endif free_irq(irq, acpi_irq); acpi_irq_handler = NULL; @@ -455,6 +462,9 @@ int result = 0; int size = 0; struct pci_bus bus; +#ifdef CONFIG_IA64 + struct pci_controller ctrl; +#endif if (!value) return AE_BAD_PARAMETER; @@ -474,6 +484,10 @@ } bus.number = pci_id->bus; +#ifdef CONFIG_IA64 + ctrl.segment = pci_id->segment; + bus.sysdata = &ctrl; +#endif result = pci_root_ops->read(&bus, PCI_DEVFN(pci_id->device, pci_id->function), reg, size, value); @@ -491,6 +505,9 @@ int result = 0; int size = 0; struct pci_bus bus; +#ifdef CONFIG_IA64 + struct pci_controller ctrl; +#endif switch (width) { case 8: @@ -507,6 +524,10 @@ } bus.number = pci_id->bus; +#ifdef CONFIG_IA64 + ctrl.segment = pci_id->segment; + bus.sysdata = &ctrl; +#endif result = pci_root_ops->write(&bus, PCI_DEVFN(pci_id->device, pci_id->function), reg, size, value); diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c --- a/drivers/acpi/pci_irq.c Thu Jun 19 00:45:34 2003 +++ b/drivers/acpi/pci_irq.c Thu Jun 19 00:45:34 2003 @@ -24,6 +24,8 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include + #include #include #include @@ -36,9 +38,16 @@ #ifdef CONFIG_X86_IO_APIC #include #endif +#ifdef CONFIG_IOSAPIC +# include +#endif #include #include +#ifdef CONFIG_X86 +# define PCI_SEGMENT(x) 0 /* XXX fix me */ +#endif + #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME ("pci_irq") @@ -248,6 +257,8 @@ return_VALUE(0); } + entry->irq = entry->link.index; + if (!entry->irq && entry->link.handle) { entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index); if (!entry->irq) { @@ -356,7 +367,11 @@ } } +#ifdef CONFIG_IA64 + dev->irq = gsi_to_irq(irq); +#else dev->irq = irq; +#endif ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", dev->slot_name, dev->irq)); @@ -369,6 +384,10 @@ irq_mask |= (1 << dev->irq); eisa_set_level_irq(dev->irq); } +#endif +#ifdef CONFIG_IOSAPIC + if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC) + iosapic_enable_intr(dev->irq); #endif return_VALUE(dev->irq); diff -Nru a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c --- a/drivers/acpi/pci_root.c Thu Jun 19 00:45:34 2003 +++ b/drivers/acpi/pci_root.c Thu Jun 19 00:45:34 2003 @@ -23,6 +23,8 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include + #include #include #include @@ -248,8 +250,6 @@ switch (status) { case AE_OK: root->id.segment = (u16) value; - printk("_SEG exists! Unsupported. Abort.\n"); - BUG(); break; case AE_NOT_FOUND: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -311,7 +311,12 @@ * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ +#ifdef CONFIG_X86 root->bus = pcibios_scan_root(root->id.bus); +#else + root->bus = pcibios_scan_root(root->handle, + root->id.segment, root->id.bus); +#endif if (!root->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Bus %02x:%02x not present in PCI namespace\n", diff -Nru a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h --- a/drivers/char/drm/drm_memory.h Thu Jun 19 00:45:34 2003 +++ b/drivers/char/drm/drm_memory.h Thu Jun 19 00:45:34 2003 @@ -32,6 +32,10 @@ #include #include #include "drmP.h" +#include + +#include +#include /* Cut down version of drm_memory_debug.h, which used to be called * drm_memory.h. If you want the debug functionality, change 0 to 1 diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Thu Jun 19 00:45:35 2003 +++ b/drivers/scsi/qla1280.c Thu Jun 19 00:45:35 2003 @@ -284,7 +284,7 @@ #define QL1280_TARGET_MODE_SUPPORT 0 /* Target mode support */ #define QL1280_LUN_SUPPORT 0 #define WATCHDOGTIMER 0 -#define MEMORY_MAPPED_IO 0 +#define MEMORY_MAPPED_IO 1 #define DEBUG_QLA1280_INTR 0 #define USE_NVRAM_DEFAULTS 0 #define DEBUG_PRINT_NVRAM 0 @@ -2491,7 +2491,7 @@ /* * Get memory mapped I/O address. */ - pci_read_config_word (ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase); + pci_read_config_dword (ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase); mmapbase &= PCI_BASE_ADDRESS_MEM_MASK; /* diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c --- a/drivers/scsi/sym53c8xx_2/sym_glue.c Thu Jun 19 00:45:35 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c Thu Jun 19 00:45:35 2003 @@ -295,11 +295,7 @@ #ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING typedef u_long bus_addr_t; #else -#if SYM_CONF_DMA_ADDRESSING_MODE > 0 -typedef dma64_addr_t bus_addr_t; -#else typedef dma_addr_t bus_addr_t; -#endif #endif /* diff -Nru a/drivers/serial/8250_hcdp.c b/drivers/serial/8250_hcdp.c --- a/drivers/serial/8250_hcdp.c Thu Jun 19 00:45:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,221 +0,0 @@ -/* - * linux/drivers/char/hcdp_serial.c - * - * Copyright (C) 2002 Hewlett-Packard Co. - * Khalid Aziz - * - * Parse the EFI HCDP table to locate serial console and debug ports and initialize them. - * - * 2002/08/29 davidm Adjust it to new 2.5 serial driver infrastructure (untested). - */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "8250_hcdp.h" - -#undef SERIAL_DEBUG_HCDP - -/* - * Parse the HCDP table to find descriptions for headless console and debug serial ports - * and add them to rs_table[]. A pointer to HCDP table is passed as parameter. This - * function should be called before serial_console_init() is called to make sure the HCDP - * serial console will be available for use. IA-64 kernel calls this function from - * setup_arch() after the EFI and ACPI tables have been parsed. - */ -void __init -setup_serial_hcdp (void *tablep) -{ - hcdp_dev_t *hcdp_dev; - struct uart_port port; - unsigned long iobase; - hcdp_t hcdp; - int gsi, nr; -#if 0 - static int shift_once = 1; -#endif - -#ifdef SERIAL_DEBUG_HCDP - printk("Entering setup_serial_hcdp()\n"); -#endif - - /* Verify we have a valid table pointer */ - if (!tablep) - return; - - memset(&port, 0, sizeof(port)); - - /* - * Don't trust firmware to give us a table starting at an aligned address. Make a - * local copy of the HCDP table with aligned structures. - */ - memcpy(&hcdp, tablep, sizeof(hcdp)); - - /* - * Perform a sanity check on the table. Table should have a signature of "HCDP" - * and it should be atleast 82 bytes long to have any useful information. - */ - if ((strncmp(hcdp.signature, HCDP_SIGNATURE, HCDP_SIG_LEN) != 0)) - return; - if (hcdp.len < 82) - return; - -#ifdef SERIAL_DEBUG_HCDP - printk("setup_serial_hcdp(): table pointer = 0x%p, sig = '%.4s'\n", - tablep, hcdp.signature); - printk(" length = %d, rev = %d, ", hcdp.len, hcdp.rev); - printk("OEM ID = %.6s, # of entries = %d\n", hcdp.oemid, hcdp.num_entries); -#endif - - /* - * Parse each device entry - */ - for (nr = 0; nr < hcdp.num_entries; nr++) { - hcdp_dev = hcdp.hcdp_dev + nr; - /* - * We will parse only the primary console device which is the first entry - * for these devices. We will ignore rest of the entries for the same type - * device that has already been parsed and initialized - */ - if (hcdp_dev->type != HCDP_DEV_CONSOLE) - continue; - - iobase = ((u64) hcdp_dev->base_addr.addrhi << 32) | hcdp_dev->base_addr.addrlo; - gsi = hcdp_dev->global_int; - - /* See PCI spec v2.2, Appendix D (Class Codes): */ - switch (hcdp_dev->pci_prog_intfc) { - case 0x00: port.type = PORT_8250; break; - case 0x01: port.type = PORT_16450; break; - case 0x02: port.type = PORT_16550; break; - case 0x03: port.type = PORT_16650; break; - case 0x04: port.type = PORT_16750; break; - case 0x05: port.type = PORT_16850; break; - case 0x06: port.type = PORT_16C950; break; - default: - printk(KERN_WARNING"warning: EFI HCDP table reports unknown serial " - "programming interface 0x%02x; will autoprobe.\n", - hcdp_dev->pci_prog_intfc); - port.type = PORT_UNKNOWN; - break; - } - -#ifdef SERIAL_DEBUG_HCDP - printk(" type = %s, uart = %d\n", ((hcdp_dev->type == HCDP_DEV_CONSOLE) - ? "Headless Console" : ((hcdp_dev->type == HCDP_DEV_DEBUG) - ? "Debug port" : "Huh????")), - port.type); - printk(" base address space = %s, base address = 0x%lx\n", - ((hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) - ? "Memory Space" : ((hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) - ? "I/O space" : "PCI space")), - iobase); - printk(" gsi = %d, baud rate = %lu, bits = %d, clock = %d\n", - gsi, (unsigned long) hcdp_dev->baud, hcdp_dev->bits, hcdp_dev->clock_rate); - if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) - printk(" PCI id: %02x:%02x:%02x, vendor ID=0x%x, dev ID=0x%x\n", - hcdp_dev->pci_seg, hcdp_dev->pci_bus, hcdp_dev->pci_dev, - hcdp_dev->pci_vendor_id, hcdp_dev->pci_dev_id); -#endif - /* - * Now fill in a port structure to update the 8250 port table.. - */ - if (hcdp_dev->clock_rate) - port.uartclk = hcdp_dev->clock_rate; - else - port.uartclk = BASE_BAUD * 16; - - /* - * Check if this is an I/O mapped address or a memory mapped address - */ - if (hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) { - port.iobase = 0; - port.mapbase = iobase; - port.membase = ioremap(iobase, 64); - port.iotype = SERIAL_IO_MEM; - } else if (hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) { - port.iobase = iobase; - port.mapbase = 0; - port.membase = NULL; - port.iotype = SERIAL_IO_PORT; - } else if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) { - printk(KERN_WARNING"warning: No support for PCI serial console\n"); - return; - } -#ifdef CONFIG_IA64 - port.irq = acpi_register_irq(gsi, ACPI_ACTIVE_HIGH, ACPI_EDGE_SENSITIVE); -#else - port.irq = gsi; -#endif - port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - if (gsi) - port.flags |= ASYNC_AUTO_IRQ; - - /* - * Note: the above memset() initializes port.line to 0, so we register - * this port as ttyS0. - */ - if (early_serial_setup(&port) < 0) { - printk("setup_serial_hcdp(): early_serial_setup() for HCDP serial " - "console port failed. Will try any additional consoles in HCDP.\n"); - continue; - } - break; - } - -#ifdef SERIAL_DEBUG_HCDP - printk("Leaving setup_serial_hcdp()\n"); -#endif -} - -#ifdef CONFIG_IA64_EARLY_PRINTK_UART -unsigned long -hcdp_early_uart (void) -{ - efi_system_table_t *systab; - efi_config_table_t *config_tables; - unsigned long addr = 0; - hcdp_t *hcdp = 0; - hcdp_dev_t *dev; - int i; - - systab = (efi_system_table_t *) ia64_boot_param->efi_systab; - if (!systab) - return 0; - systab = __va(systab); - - config_tables = (efi_config_table_t *) systab->tables; - if (!config_tables) - return 0; - config_tables = __va(config_tables); - - for (i = 0; i < systab->nr_tables; i++) { - if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - hcdp = (hcdp_t *) config_tables[i].table; - break; - } - } - if (!hcdp) - return 0; - hcdp = __va(hcdp); - - for (i = 0, dev = hcdp->hcdp_dev; i < hcdp->num_entries; i++, dev++) { - if (dev->type == HCDP_DEV_CONSOLE) { - addr = (u64) dev->base_addr.addrhi << 32 | dev->base_addr.addrlo; - break; - } - } - return addr; -} -#endif /* CONFIG_IA64_EARLY_PRINTK_UART */ diff -Nru a/drivers/serial/8250_hcdp.h b/drivers/serial/8250_hcdp.h --- a/drivers/serial/8250_hcdp.h Thu Jun 19 00:45:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,79 +0,0 @@ -/* - * drivers/serial/8250_hcdp.h - * - * Copyright (C) 2002 Hewlett-Packard Co. - * Khalid Aziz - * - * Definitions for HCDP defined serial ports (Serial console and debug - * ports) - */ - -/* ACPI table signatures */ -#define HCDP_SIG_LEN 4 -#define HCDP_SIGNATURE "HCDP" - -/* Space ID as defined in ACPI generic address structure */ -#define ACPI_MEM_SPACE 0 -#define ACPI_IO_SPACE 1 -#define ACPI_PCICONF_SPACE 2 - -/* - * Maximum number of HCDP devices we want to read in - */ -#define MAX_HCDP_DEVICES 6 - -/* - * Default UART clock rate if clock rate is 0 in HCDP table. - */ -#define DEFAULT_UARTCLK 115200 - -/* - * ACPI Generic Address Structure - */ -typedef struct { - u8 space_id; - u8 bit_width; - u8 bit_offset; - u8 resv; - u32 addrlo; - u32 addrhi; -} acpi_gen_addr; - -/* HCDP Device descriptor entry types */ -#define HCDP_DEV_CONSOLE 0 -#define HCDP_DEV_DEBUG 1 - -/* HCDP Device descriptor type */ -typedef struct { - u8 type; - u8 bits; - u8 parity; - u8 stop_bits; - u8 pci_seg; - u8 pci_bus; - u8 pci_dev; - u8 pci_func; - u64 baud; - acpi_gen_addr base_addr; - u16 pci_dev_id; - u16 pci_vendor_id; - u32 global_int; - u32 clock_rate; - u8 pci_prog_intfc; - u8 resv; -} hcdp_dev_t; - -/* HCDP Table format */ -typedef struct { - u8 signature[4]; - u32 len; - u8 rev; - u8 chksum; - u8 oemid[6]; - u8 oem_tabid[8]; - u32 oem_rev; - u8 creator_id[4]; - u32 creator_rev; - u32 num_entries; - hcdp_dev_t hcdp_dev[MAX_HCDP_DEVICES]; -} hcdp_t; diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Thu Jun 19 00:45:34 2003 +++ b/drivers/serial/Kconfig Thu Jun 19 00:45:34 2003 @@ -77,7 +77,7 @@ a module, say M here and read . If unsure, say N. -config SERIAL_HCDP +config SERIAL_8250_HCDP bool "8250/16550 device discovery support via EFI HCDP table" depends on IA64 ---help--- diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- a/drivers/serial/Makefile Thu Jun 19 00:45:34 2003 +++ b/drivers/serial/Makefile Thu Jun 19 00:45:34 2003 @@ -9,6 +9,7 @@ serial-8250-$(CONFIG_PCI) += 8250_pci.o serial-8250-$(CONFIG_PNP) += 8250_pnp.o serial-8250-$(CONFIG_SERIAL_HCDP) += 8250_hcdp.o +serial-8250-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_SERIAL_CORE) += core.o obj-$(CONFIG_SERIAL_21285) += 21285.o diff -Nru a/fs/fcntl.c b/fs/fcntl.c --- a/fs/fcntl.c Thu Jun 19 00:45:34 2003 +++ b/fs/fcntl.c Thu Jun 19 00:45:34 2003 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -80,11 +81,11 @@ */ static int locate_fd(struct files_struct *files, - struct file *file, int orig_start) + struct file *file, unsigned int orig_start) { unsigned int newfd; + unsigned int start; int error; - int start; error = -EINVAL; if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur) @@ -129,7 +130,7 @@ return error; } -static int dupfd(struct file *file, int start) +static int dupfd(struct file *file, unsigned int start) { struct files_struct * files = current->files; int fd; @@ -286,10 +287,8 @@ switch (cmd) { case F_DUPFD: - if (arg < NR_OPEN) { - get_file(filp); - err = dupfd(filp, arg); - } + get_file(filp); + err = dupfd(filp, arg); break; case F_GETFD: err = get_close_on_exec(fd); @@ -305,11 +304,11 @@ err = setfl(fd, filp, arg); break; case F_GETLK: - err = fcntl_getlk(filp, (struct flock *) arg); + err = fcntl_getlk(filp, (struct flock __user *) arg); break; case F_SETLK: case F_SETLKW: - err = fcntl_setlk(filp, cmd, (struct flock *) arg); + err = fcntl_setlk(filp, cmd, (struct flock __user *) arg); break; case F_GETOWN: /* @@ -394,11 +393,11 @@ switch (cmd) { case F_GETLK64: - err = fcntl_getlk64(filp, (struct flock64 *) arg); + err = fcntl_getlk64(filp, (struct flock64 __user *) arg); break; case F_SETLK64: case F_SETLKW64: - err = fcntl_setlk64(filp, cmd, (struct flock64 *) arg); + err = fcntl_setlk64(filp, cmd, (struct flock64 __user *) arg); break; default: err = do_fcntl(fd, cmd, arg, filp); diff -Nru a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c Thu Jun 19 00:45:34 2003 +++ b/fs/proc/base.c Thu Jun 19 00:45:34 2003 @@ -58,6 +58,13 @@ PROC_PID_MAPS, PROC_PID_MOUNTS, PROC_PID_WCHAN, +#ifdef CONFIG_SECURITY + PROC_PID_ATTR, + PROC_PID_ATTR_CURRENT, + PROC_PID_ATTR_PREV, + PROC_PID_ATTR_EXEC, + PROC_PID_ATTR_FSCREATE, +#endif PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */ }; @@ -82,11 +89,23 @@ E(PROC_PID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_PID_EXE, "exe", S_IFLNK|S_IRWXUGO), E(PROC_PID_MOUNTS, "mounts", S_IFREG|S_IRUGO), +#ifdef CONFIG_SECURITY + E(PROC_PID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), +#endif #ifdef CONFIG_KALLSYMS E(PROC_PID_WCHAN, "wchan", S_IFREG|S_IRUGO), #endif {0,0,NULL,0} }; +#ifdef CONFIG_SECURITY +static struct pid_entry attr_stuff[] = { + E(PROC_PID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO), + E(PROC_PID_ATTR_PREV, "prev", S_IFREG|S_IRUGO), + E(PROC_PID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), + E(PROC_PID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), + {0,0,NULL,0} +}; +#endif #undef E static inline struct task_struct *proc_task(struct inode *inode) @@ -322,21 +341,23 @@ return proc_check_root(inode); } -extern ssize_t proc_pid_read_maps(struct task_struct *, struct file *, - char *, size_t, loff_t *); -static ssize_t pid_maps_read(struct file * file, char * buf, - size_t count, loff_t *ppos) +extern struct seq_operations proc_pid_maps_op; +static int maps_open(struct inode *inode, struct file *file) { - struct inode * inode = file->f_dentry->d_inode; struct task_struct *task = proc_task(inode); - ssize_t res; - - res = proc_pid_read_maps(task, file, buf, count, ppos); - return res; + int ret = seq_open(file, &proc_pid_maps_op); + if (!ret) { + struct seq_file *m = file->private_data; + m->private = task; + } + return ret; } static struct file_operations proc_maps_operations = { - .read = pid_maps_read, + .open = maps_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; extern struct seq_operations mounts_op; @@ -409,8 +430,10 @@ if (count + *ppos > length) count = length - *ppos; end = count + *ppos; - copy_to_user(buf, (char *) page + *ppos, count); - *ppos = end; + if (copy_to_user(buf, (char *) page + *ppos, count)) + count = -EFAULT; + else + *ppos = end; free_page(page); return count; } @@ -537,13 +560,13 @@ static loff_t mem_lseek(struct file * file, loff_t offset, int orig) { switch (orig) { - case 0: + case 0: file->f_pos = offset; break; - case 1: + case 1: file->f_pos += offset; break; - default: + default: return -EINVAL; } force_successful_syscall_return(); @@ -639,6 +662,12 @@ .follow_link = proc_pid_follow_link }; +static int pid_alive(struct task_struct *p) +{ + BUG_ON(p->pids[PIDTYPE_PID].pidptr != &p->pids[PIDTYPE_PID].pid); + return atomic_read(&p->pids[PIDTYPE_PID].pid.count); +} + #define NUMBUF 10 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) @@ -650,6 +679,9 @@ char buf[NUMBUF]; struct files_struct * files; + retval = -ENOENT; + if (!pid_alive(p)) + goto out; retval = 0; pid = p->pid; @@ -704,58 +736,68 @@ return retval; } -static int proc_base_readdir(struct file * filp, - void * dirent, filldir_t filldir) +static int proc_pident_readdir(struct file *filp, + void *dirent, filldir_t filldir, + struct pid_entry *ents, unsigned int nents) { int i; int pid; - struct inode *inode = filp->f_dentry->d_inode; + struct dentry *dentry = filp->f_dentry; + struct inode *inode = dentry->d_inode; struct pid_entry *p; - int ret = 0; + ino_t ino; + int ret; - lock_kernel(); + ret = -ENOENT; + if (!pid_alive(proc_task(inode))) + goto out; + ret = 0; pid = proc_task(inode)->pid; - if (!pid) { - ret = -ENOENT; - goto out; - } i = filp->f_pos; switch (i) { - case 0: - if (filldir(dirent, ".", 1, i, inode->i_ino, DT_DIR) < 0) - goto out; - i++; - filp->f_pos++; - /* fall through */ - case 1: - if (filldir(dirent, "..", 2, i, PROC_ROOT_INO, DT_DIR) < 0) + case 0: + ino = inode->i_ino; + if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) + goto out; + i++; + filp->f_pos++; + /* fall through */ + case 1: + ino = parent_ino(dentry); + if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) + goto out; + i++; + filp->f_pos++; + /* fall through */ + default: + i -= 2; + if (i >= nents) { + ret = 1; + goto out; + } + p = ents + i; + while (p->name) { + if (filldir(dirent, p->name, p->len, filp->f_pos, + fake_ino(pid, p->type), p->mode >> 12) < 0) goto out; - i++; filp->f_pos++; - /* fall through */ - default: - i -= 2; - if (i>=sizeof(base_stuff)/sizeof(base_stuff[0])) { - ret = 1; - goto out; - } - p = base_stuff + i; - while (p->name) { - if (filldir(dirent, p->name, p->len, filp->f_pos, - fake_ino(pid, p->type), p->mode >> 12) < 0) - goto out; - filp->f_pos++; - p++; - } + p++; + } } ret = 1; out: - unlock_kernel(); return ret; } +static int proc_base_readdir(struct file * filp, + void * dirent, filldir_t filldir) +{ + return proc_pident_readdir(filp,dirent,filldir, + base_stuff,ARRAY_SIZE(base_stuff)); +} + /* building an inode */ static int task_dumpable(struct task_struct *task) @@ -789,7 +831,7 @@ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(task->pid, ino); - if (!task->pid) + if (!pid_alive(task)) goto out_unlock; /* @@ -804,6 +846,7 @@ inode->i_uid = task->euid; inode->i_gid = task->egid; } + security_task_to_inode(task, inode); out: return inode; @@ -823,7 +866,7 @@ */ static int pid_revalidate(struct dentry * dentry, int flags) { - if (proc_task(dentry->d_inode)->pid) + if (pid_alive(proc_task(dentry->d_inode))) return 1; d_drop(dentry); return 0; @@ -857,18 +900,23 @@ static void pid_base_iput(struct dentry *dentry, struct inode *inode) { struct task_struct *task = proc_task(inode); - write_lock_irq(&tasklist_lock); + spin_lock(&task->proc_lock); if (task->proc_dentry == dentry) task->proc_dentry = NULL; - write_unlock_irq(&tasklist_lock); + spin_unlock(&task->proc_lock); iput(inode); } static int pid_delete_dentry(struct dentry * dentry) { - return proc_task(dentry->d_inode)->pid == 0; + /* Is the task we represent dead? + * If so, then don't put the dentry on the lru list, + * kill it immediately. + */ + return !pid_alive(proc_task(dentry->d_inode)); } + static struct dentry_operations pid_fd_dentry_operations = { .d_revalidate = pid_fd_revalidate, @@ -924,6 +972,8 @@ if (fd == ~0U) goto out; + if (!pid_alive(task)) + goto out; inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd); if (!inode) @@ -952,8 +1002,6 @@ ei->op.proc_get_link = proc_fd_link; dentry->d_op = &pid_fd_dentry_operations; d_add(dentry, inode); - if (!proc_task(dentry->d_inode)->pid) - d_drop(dentry); return NULL; out_unlock2: @@ -978,8 +1026,86 @@ .permission = proc_permission, }; +#ifdef CONFIG_SECURITY +static ssize_t proc_pid_attr_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + struct inode * inode = file->f_dentry->d_inode; + unsigned long page; + ssize_t length; + ssize_t end; + struct task_struct *task = proc_task(inode); + + if (count > PAGE_SIZE) + count = PAGE_SIZE; + if (!(page = __get_free_page(GFP_KERNEL))) + return -ENOMEM; + + length = security_getprocattr(task, + (char*)file->f_dentry->d_name.name, + (void*)page, count); + if (length < 0) { + free_page(page); + return length; + } + /* Static 4kB (or whatever) block capacity */ + if (*ppos >= length) { + free_page(page); + return 0; + } + if (count + *ppos > length) + count = length - *ppos; + end = count + *ppos; + if (copy_to_user(buf, (char *) page + *ppos, count)) + count = -EFAULT; + else + *ppos = end; + free_page(page); + return count; +} + +static ssize_t proc_pid_attr_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + struct inode * inode = file->f_dentry->d_inode; + char *page; + ssize_t length; + struct task_struct *task = proc_task(inode); + + if (count > PAGE_SIZE) + count = PAGE_SIZE; + if (*ppos != 0) { + /* No partial writes. */ + return -EINVAL; + } + page = (char*)__get_free_page(GFP_USER); + if (!page) + return -ENOMEM; + length = -EFAULT; + if (copy_from_user(page, buf, count)) + goto out; + + length = security_setprocattr(task, + (char*)file->f_dentry->d_name.name, + (void*)page, count); +out: + free_page((unsigned long) page); + return length; +} + +static struct file_operations proc_pid_attr_operations = { + .read = proc_pid_attr_read, + .write = proc_pid_attr_write, +}; + +static struct file_operations proc_attr_operations; +static struct inode_operations proc_attr_inode_operations; +#endif + /* SMP-safe */ -static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) +static struct dentry *proc_pident_lookup(struct inode *dir, + struct dentry *dentry, + struct pid_entry *ents) { struct inode *inode; int error; @@ -990,7 +1116,10 @@ error = -ENOENT; inode = NULL; - for (p = base_stuff; p->name; p++) { + if (!pid_alive(task)) + goto out; + + for (p = ents; p->name; p++) { if (p->len != dentry->d_name.len) continue; if (!memcmp(dentry->d_name.name, p->name, p->len)) @@ -1058,6 +1187,19 @@ case PROC_PID_MOUNTS: inode->i_fop = &proc_mounts_operations; break; +#ifdef CONFIG_SECURITY + case PROC_PID_ATTR: + inode->i_nlink = 2; + inode->i_op = &proc_attr_inode_operations; + inode->i_fop = &proc_attr_operations; + break; + case PROC_PID_ATTR_CURRENT: + case PROC_PID_ATTR_PREV: + case PROC_PID_ATTR_EXEC: + case PROC_PID_ATTR_FSCREATE: + inode->i_fop = &proc_pid_attr_operations; + break; +#endif #ifdef CONFIG_KALLSYMS case PROC_PID_WCHAN: inode->i_fop = &proc_info_file_operations; @@ -1071,14 +1213,16 @@ } dentry->d_op = &pid_dentry_operations; d_add(dentry, inode); - if (!proc_task(dentry->d_inode)->pid) - d_drop(dentry); return NULL; out: return ERR_PTR(error); } +static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry){ + return proc_pident_lookup(dir, dentry, base_stuff); +} + static struct file_operations proc_base_operations = { .read = generic_read_dir, .readdir = proc_base_readdir, @@ -1088,6 +1232,28 @@ .lookup = proc_base_lookup, }; +#ifdef CONFIG_SECURITY +static int proc_attr_readdir(struct file * filp, + void * dirent, filldir_t filldir) +{ + return proc_pident_readdir(filp,dirent,filldir, + attr_stuff,ARRAY_SIZE(attr_stuff)); +} + +static struct file_operations proc_attr_operations = { + .read = generic_read_dir, + .readdir = proc_attr_readdir, +}; + +static struct dentry *proc_attr_lookup(struct inode *dir, struct dentry *dentry){ + return proc_pident_lookup(dir, dentry, attr_stuff); +} + +static struct inode_operations proc_attr_inode_operations = { + .lookup = proc_attr_lookup, +}; +#endif + /* * /proc/self: */ @@ -1110,6 +1276,55 @@ .follow_link = proc_self_follow_link, }; +/** + * proc_pid_unhash - Unhash /proc/ entry from the dcache. + * @p: task that should be flushed. + * + * Drops the /proc/ dcache entry from the hash chains. + * + * Dropping /proc/ entries and detach_pid must be synchroneous, + * otherwise e.g. /proc//exe might point to the wrong executable, + * if the pid value is immediately reused. This is enforced by + * - caller must acquire spin_lock(p->proc_lock) + * - must be called before detach_pid() + * - proc_pid_lookup acquires proc_lock, and checks that + * the target is not dead by looking at the attach count + * of PIDTYPE_PID. + */ + +struct dentry *proc_pid_unhash(struct task_struct *p) +{ + struct dentry *proc_dentry; + + proc_dentry = p->proc_dentry; + if (proc_dentry != NULL) { + + spin_lock(&dcache_lock); + if (!d_unhashed(proc_dentry)) { + dget_locked(proc_dentry); + __d_drop(proc_dentry); + } else + proc_dentry = NULL; + spin_unlock(&dcache_lock); + } + return proc_dentry; +} + +/** + * proc_pid_flush - recover memory used by stale /proc//x entries + * @proc_entry: directoy to prune. + * + * Shrink the /proc directory that was used by the just killed thread. + */ + +void proc_pid_flush(struct dentry *proc_dentry) +{ + if(proc_dentry != NULL) { + shrink_dcache_parent(proc_dentry); + dput(proc_dentry); + } +} + /* SMP-safe */ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry) { @@ -1158,12 +1373,12 @@ inode->i_flags|=S_IMMUTABLE; dentry->d_op = &pid_base_dentry_operations; + + spin_lock(&task->proc_lock); + task->proc_dentry = dentry; d_add(dentry, inode); - read_lock(&tasklist_lock); - proc_task(dentry->d_inode)->proc_dentry = dentry; - read_unlock(&tasklist_lock); - if (!proc_task(dentry->d_inode)->pid) - d_drop(dentry); + spin_unlock(&task->proc_lock); + return NULL; out: return ERR_PTR(-ENOENT); @@ -1186,7 +1401,7 @@ read_lock(&tasklist_lock); for_each_process(p) { int pid = p->pid; - if (!pid) + if (!pid_alive(p)) continue; if (--index >= 0) continue; diff -Nru a/fs/select.c b/fs/select.c --- a/fs/select.c Thu Jun 19 00:45:34 2003 +++ b/fs/select.c Thu Jun 19 00:45:34 2003 @@ -194,6 +194,7 @@ retval = 0; for (;;) { unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; + set_current_state(TASK_INTERRUPTIBLE); inp = fds->in; outp = fds->out; exp = fds->ex; @@ -238,9 +239,12 @@ } } } - if (res_in) *rinp = res_in; - if (res_out) *routp = res_out; - if (res_ex) *rexp = res_ex; + if (res_in) + *rinp = res_in; + if (res_out) + *routp = res_out; + if (res_ex) + *rexp = res_ex; } wait = NULL; if (retval || !__timeout || signal_pending(current)) diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h --- a/include/asm-alpha/unistd.h Thu Jun 19 00:45:34 2003 +++ b/include/asm-alpha/unistd.h Thu Jun 19 00:45:34 2003 @@ -616,6 +616,8 @@ #endif /* __KERNEL_SYSCALLS__ */ +#ifdef __KERNEL__ + /* * "Conditional" syscalls * @@ -628,4 +630,25 @@ */ #define cond_syscall(x) asmlinkage long x() __attribute__((weak,alias("sys_ni_syscall"))); +/* + * System call handlers that, upon successful completion, need to return a negative value + * should call force_successful_syscall_return() right before returning. On architectures + * where the syscall convention provides for a separate error flag (e.g., alpha, ia64, + * ppc{,64}, sparc{,64}, possibly others), this macro can be used to ensure that the error + * flag will not get set. On architectures which do not support a separate error flag, + * the macro is a no-op and the spurious error condition needs to be filtered out by some + * other means (e.g., in user-level, by passing an extra argument to the syscall handler, + * or something along those lines). + * + * On alpha, we can clear the user's pt_regs->r0 to force a successful syscall. + * + * XXX TODO: if kernel-only threads do not have a dummy pt_regs structure at the top + * of the stack, this would cause kernel stack corruption. Either check + * first that we're not dealing with a kernel thread or change the kernel + * stacks to allocate a dummy pt_regs structure. + */ +#define alpha_task_regs(task) ((struct pt_regs *) ((long) task->thread_info + PAGE_SIZE) - 1) +#define force_successful_syscall_return() (alpha_task_regs(current)->r0 = 0) + +#endif /* __KERNEL__ */ #endif /* _ALPHA_UNISTD_H */ diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h --- a/include/asm-i386/unistd.h Thu Jun 19 00:45:34 2003 +++ b/include/asm-i386/unistd.h Thu Jun 19 00:45:34 2003 @@ -393,29 +393,14 @@ #endif -#ifdef __KERNEL__ - /* * "Conditional" syscalls * * What we want is __attribute__((weak,alias("sys_ni_syscall"))), * but it doesn't work on all toolchains, so we just do it by hand */ +#ifndef cond_syscall #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall"); +#endif -/* - * System call handlers that, upon successful completion, need to return a negative value - * should call force_successful_syscall_return() right before returning. On architectures - * where the syscall convention provides for a separate error flag (e.g., alpha, ia64, - * ppc{,64}, sparc{,64}, possibly others), this macro can be used to ensure that the error - * flag will not get set. On architectures which do not support a separate error flag, - * the macro is a no-op and the spurious error condition needs to be filtered out by some - * other means (e.g., in user-level, by passing an extra argument to the syscall handler, - * or something along those lines). - * - * On x86, this is a no-op. - */ -#define force_successful_syscall_return() - -#endif /* __KERNEL__ */ #endif /* _ASM_I386_UNISTD_H_ */ diff -Nru a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h --- a/include/asm-ppc64/mmzone.h Thu Jun 19 00:45:34 2003 +++ b/include/asm-ppc64/mmzone.h Thu Jun 19 00:45:34 2003 @@ -18,9 +18,10 @@ * Following are specific to this numa platform. */ -extern int numa_node_exists[]; extern int numa_cpu_lookup_table[]; extern int numa_memory_lookup_table[]; +extern unsigned long numa_cpumask_lookup_table[]; +extern int nr_cpus_in_node[]; #define MAX_MEMORY (1UL << 41) /* 256MB regions */ diff -Nru a/include/asm-ppc64/module.h b/include/asm-ppc64/module.h --- a/include/asm-ppc64/module.h Thu Jun 19 00:45:34 2003 +++ b/include/asm-ppc64/module.h Thu Jun 19 00:45:34 2003 @@ -1,6 +1,9 @@ #ifndef _ASM_PPC64_MODULE_H #define _ASM_PPC64_MODULE_H +#include +#include + struct mod_arch_specific { /* Index of stubs section within module. */ @@ -8,7 +11,14 @@ /* What section is the TOC? */ unsigned int toc_section; + + /* List of BUG addresses, source line numbers and filenames */ + struct list_head bug_list; + struct bug_entry *bug_table; + unsigned int num_bugs; }; + +extern struct bug_entry *module_find_bug(unsigned long bugaddr); #define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h --- a/include/asm-ppc64/processor.h Thu Jun 19 00:45:34 2003 +++ b/include/asm-ppc64/processor.h Thu Jun 19 00:45:34 2003 @@ -469,8 +469,6 @@ #define IOCR_SPC 0x00000001 -/* Processor Version Register */ - /* Processor Version Register (PVR) field extraction */ #define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ @@ -595,6 +593,8 @@ asm volatile("mfasr %0" : "=r" (rval)); rval;}) #ifndef __ASSEMBLY__ +extern unsigned long *_get_SP(void); + extern int have_of; struct task_struct; @@ -654,8 +654,10 @@ struct pt_regs *regs; /* Pointer to saved register state */ mm_segment_t fs; /* for get_fs() validation */ double fpr[32]; /* Complete floating point set */ - unsigned long fpscr; /* Floating point status */ - unsigned int fpexc_mode; /* Floating-point exception mode */ + unsigned long fpscr; /* Floating point status (plus pad) */ + unsigned long fpexc_mode; /* Floating-point exception mode */ + unsigned long saved_msr; /* Save MSR across signal handlers */ + unsigned long saved_softe; /* Ditto for Soft Enable/Disable */ }; #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) @@ -702,7 +704,7 @@ return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); } -static inline unsigned int __pack_fe01(unsigned int fpmode) +static inline unsigned long __pack_fe01(unsigned int fpmode) { return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1); } @@ -728,17 +730,14 @@ #define spin_lock_prefetch(x) prefetchw(x) -#define cpu_has_largepage() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) - -#define cpu_has_slb() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) +/* XXX we have to call HV to set when in LPAR */ +#define cpu_has_dabr() (1) -#define cpu_has_tlbiel() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) +#define cpu_has_iabr() (processor_type() != PV_POWER4 && \ + processor_type() != PV_POWER4p) -#define cpu_has_noexecute() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) +#define cpu_alignexc_sets_dsisr() (processor_type() != PV_POWER4 && \ + processor_type() != PV_POWER4p) #endif /* ASSEMBLY */ diff -Nru a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h --- a/include/asm-ppc64/topology.h Thu Jun 19 00:45:34 2003 +++ b/include/asm-ppc64/topology.h Thu Jun 19 00:45:34 2003 @@ -20,32 +20,25 @@ return node; } -static inline int node_to_first_cpu(int node) -{ - int cpu; +#define memblk_to_node(memblk) (memblk) - for(cpu = 0; cpu < NR_CPUS; cpu++) - if (numa_cpu_lookup_table[cpu] == node) - return cpu; +#define parent_node(node) (node) - BUG(); /* couldn't find a cpu on given node */ - return -1; +static inline unsigned long node_to_cpumask(int node) +{ + return numa_cpumask_lookup_table[node]; } -static inline unsigned long node_to_cpumask(int node) +static inline int node_to_first_cpu(int node) { - int cpu; - unsigned long mask = 0UL; + return __ffs(node_to_cpumask(node)); +} - if (sizeof(unsigned long) * 8 < NR_CPUS) - BUG(); +#define node_to_memblk(node) (node) - for(cpu = 0; cpu < NR_CPUS; cpu++) - if (numa_cpu_lookup_table[cpu] == node) - mask |= 1UL << cpu; +#define pcibus_to_cpumask(bus) (cpu_online_map) - return mask; -} +#define nr_cpus_node(node) (nr_cpus_in_node[node]) /* Cross-node load balancing interval. */ #define NODE_BALANCE_RATE 10 diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h --- a/include/asm-ppc64/unistd.h Thu Jun 19 00:45:34 2003 +++ b/include/asm-ppc64/unistd.h Thu Jun 19 00:45:34 2003 @@ -260,7 +260,7 @@ #define __NR_clock_getres 247 #define __NR_clock_nanosleep 248 -#define __NR_syscalls 239 +#define __NR_syscalls 249 #ifdef __KERNEL__ #define NR_syscalls __NR_syscalls #endif @@ -390,6 +390,8 @@ #endif /* __KERNEL_SYSCALLS__ */ +#ifdef __KERNEL__ + /* * "Conditional" syscalls * @@ -397,6 +399,23 @@ * but it doesn't work on all toolchains, so we just do it by hand */ #define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall"); + +/* + * System call handlers that, upon successful completion, need to return a negative value + * should call force_successful_syscall_return() right before returning. On architectures + * where the syscall convention provides for a separate error flag (e.g., alpha, ia64, + * ppc{,64}, sparc{,64}, possibly others), this macro can be used to ensure that the error + * flag will not get set. On architectures which do not support a separate error flag, + * the macro is a no-op and the spurious error condition needs to be filtered out by some + * other means (e.g., in user-level, by passing an extra argument to the syscall handler, + * or something along those lines). + * + * On PPC64, the syscall error flag is returned via the SO bit in CR, but for now there is + * no way to force that bit to zero, so we do nothing here. + */ +#define force_successful_syscall_return() + +#endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h --- a/include/linux/highmem.h Thu Jun 19 00:45:34 2003 +++ b/include/linux/highmem.h Thu Jun 19 00:45:34 2003 @@ -3,6 +3,8 @@ #include #include +#include + #include #ifdef CONFIG_HIGHMEM diff -Nru a/include/linux/irq.h b/include/linux/irq.h --- a/include/linux/irq.h Thu Jun 19 00:45:34 2003 +++ b/include/linux/irq.h Thu Jun 19 00:45:34 2003 @@ -56,7 +56,7 @@ * * Pad this out to 32 bytes for cache and indexing reasons. */ -typedef struct { +typedef struct irq_desc { unsigned int status; /* IRQ status */ hw_irq_controller *handler; struct irqaction *action; /* IRQ action list */ @@ -65,8 +65,6 @@ unsigned int irqs_unhandled; spinlock_t lock; } ____cacheline_aligned irq_desc_t; - -extern irq_desc_t irq_desc [NR_IRQS]; #include /* the arch dependent stuff */ diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h Thu Jun 19 00:45:34 2003 +++ b/include/linux/pci_ids.h Thu Jun 19 00:45:34 2003 @@ -602,6 +602,8 @@ #define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 #define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A #define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B +#define PCI_DEVICE_ID_HP_REO_SBA 0x10f0 +#define PCI_DEVICE_ID_HP_REO_IOC 0x10f1 #define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b #define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 #define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Thu Jun 19 00:45:34 2003 +++ b/include/linux/sched.h Thu Jun 19 00:45:34 2003 @@ -148,10 +148,15 @@ extern void init_idle(task_t *idle, int cpu); extern void show_state(void); -extern void show_trace(unsigned long *stack); -extern void show_stack(unsigned long *stack); extern void show_regs(struct pt_regs *); +/* + * TASK is a pointer to the task whose backtrace we want to see (or NULL for current + * task), SP is the stack pointer of the first frame that should be shown in the back + * trace (or NULL if the entire call-chain of the task should be shown). + */ +extern void show_stack(struct task_struct *task, unsigned long *sp); + void io_schedule(void); long io_schedule_timeout(long timeout); @@ -506,14 +511,14 @@ #ifndef INIT_THREAD_SIZE # define INIT_THREAD_SIZE 2048*sizeof(long) -#endif - union thread_union { struct thread_info thread_info; unsigned long stack[INIT_THREAD_SIZE/sizeof(long)]; }; extern union thread_union init_thread_union; +#endif + extern struct task_struct init_task; extern struct mm_struct init_mm; diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h --- a/include/linux/sunrpc/svc.h Thu Jun 19 00:45:34 2003 +++ b/include/linux/sunrpc/svc.h Thu Jun 19 00:45:34 2003 @@ -176,8 +176,10 @@ { if (rqstp->rq_arghi <= rqstp->rq_argused) return -ENOMEM; - rqstp->rq_respages[rqstp->rq_resused++] = - rqstp->rq_argpages[--rqstp->rq_arghi]; + rqstp->rq_arghi--; + rqstp->rq_respages[rqstp->rq_resused] = + rqstp->rq_argpages[rqstp->rq_arghi]; + rqstp->rq_resused++; return 0; } diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h --- a/include/linux/sysctl.h Thu Jun 19 00:45:34 2003 +++ b/include/linux/sysctl.h Thu Jun 19 00:45:34 2003 @@ -130,6 +130,7 @@ KERN_PIDMAX=55, /* int: PID # limit */ KERN_CORE_PATTERN=56, /* string: pattern for core-file names */ KERN_PANIC_ON_OOPS=57, /* int: whether we will panic on an oops */ + KERN_CACHEDECAYTICKS=58, /* ulong: value for cache_decay_ticks (EXPERIMENTAL!) */ }; diff -Nru a/include/linux/time.h b/include/linux/time.h --- a/include/linux/time.h Thu Jun 19 00:45:34 2003 +++ b/include/linux/time.h Thu Jun 19 00:45:34 2003 @@ -162,7 +162,7 @@ extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); extern void clock_was_set(void); // call when ever the clock is set extern long do_nanosleep(struct timespec *t); -extern long do_utimes(char * filename, struct timeval * times); +extern long do_utimes(char __user * filename, struct timeval * times); #endif #define FD_SETSIZE __FD_SETSIZE diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Thu Jun 19 00:45:34 2003 +++ b/kernel/fork.c Thu Jun 19 00:45:34 2003 @@ -888,11 +888,15 @@ if (clone_flags & CLONE_CHILD_SETTID) p->set_child_tid = child_tidptr; + else + p->set_child_tid = NULL; /* * Clear TID on mm_release()? */ if (clone_flags & CLONE_CHILD_CLEARTID) p->clear_child_tid = child_tidptr; + else + p->clear_child_tid = NULL; /* * Syscall tracing should be turned off in the child regardless diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Thu Jun 19 00:45:34 2003 +++ b/kernel/ksyms.c Thu Jun 19 00:45:34 2003 @@ -592,7 +592,9 @@ /* init task, for moving kthread roots - ought to export a function ?? */ EXPORT_SYMBOL(init_task); +#ifndef CONFIG_IA64 EXPORT_SYMBOL(init_thread_union); +#endif EXPORT_SYMBOL(tasklist_lock); EXPORT_SYMBOL(find_task_by_pid); diff -Nru a/kernel/posix-timers.c b/kernel/posix-timers.c --- a/kernel/posix-timers.c Thu Jun 19 00:45:34 2003 +++ b/kernel/posix-timers.c Thu Jun 19 00:45:34 2003 @@ -33,12 +33,7 @@ result; }) #endif -#define CLOCK_REALTIME_RES TICK_NSEC(TICK_USEC) // In nano seconds. -static inline u64 mpy_l_X_l_ll(unsigned long mpy1,unsigned long mpy2) -{ - return (u64)mpy1 * mpy2; -} /* * Management arrays for POSIX timers. Timers are kept in slab memory * Timer ids are allocated by an external routine that keeps track of the @@ -180,8 +175,8 @@ */ static __init int init_posix_timers(void) { - struct k_clock clock_realtime = {.res = CLOCK_REALTIME_RES }; - struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES, + struct k_clock clock_realtime = {.res = NSEC_PER_SEC / HZ }; + struct k_clock clock_monotonic = {.res = NSEC_PER_SEC / HZ, .clock_get = do_posix_clock_monotonic_gettime, .clock_set = do_posix_clock_monotonic_settime }; @@ -209,14 +204,24 @@ } /* - * The scaling constants are defined in - * The difference between there and here is that we do the - * res rounding and compute a 64-bit result (well so does that - * but it then throws away the high bits). - */ - *jiff = (mpy_l_X_l_ll(sec, SEC_CONVERSION) + - (mpy_l_X_l_ll(nsec, NSEC_CONVERSION) >> - (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; + * A note on jiffy overflow: It is possible for the system to + * have been up long enough for the jiffies quanity to overflow. + * In order for correct timer evaluations we require that the + * specified time be somewhere between now and now + (max + * unsigned int/2). Times beyond this will be truncated back to + * this value. This is done in the absolute adjustment code, + * below. Here it is enough to just discard the high order + * bits. + */ + *jiff = (s64)sec * HZ; + /* + * Do the res thing. (Don't forget the add in the declaration of nsec) + */ + nsec -= nsec % res; + /* + * Split to jiffie and sub jiffie + */ + *jiff += nsec / (NSEC_PER_SEC / HZ); } static void schedule_next_timer(struct k_itimer *timr) @@ -1215,6 +1220,7 @@ finish_wait(&nanosleep_abs_wqueue, &abs_wqueue); if (left > (s64)0) { + unsigned long rmd; /* * Always restart abs calls from scratch to pick up any @@ -1223,10 +1229,9 @@ if (abs) return -ERESTARTNOHAND; - left *= TICK_NSEC(TICK_USEC); - tsave->tv_sec = div_long_long_rem(left, - NSEC_PER_SEC, - &tsave->tv_nsec); + tsave->tv_sec = div_long_long_rem(left, HZ, &rmd); + tsave->tv_nsec = rmd * (NSEC_PER_SEC / HZ); + restart_block->fn = clock_nanosleep_restart; restart_block->arg0 = which_clock; restart_block->arg1 = (unsigned long)tsave; diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Thu Jun 19 00:45:34 2003 +++ b/kernel/sched.c Thu Jun 19 00:45:34 2003 @@ -2179,10 +2179,7 @@ else printk(" (NOTLB)\n"); - { - extern void show_trace_task(task_t *tsk); - show_trace_task(p); - } + show_stack(p, NULL); } void show_state(void) diff -Nru a/kernel/sys.c b/kernel/sys.c --- a/kernel/sys.c Thu Jun 19 00:45:34 2003 +++ b/kernel/sys.c Thu Jun 19 00:45:34 2003 @@ -1219,7 +1219,7 @@ ? -EFAULT : 0; } -#if !defined(__ia64__) && !defined(CONFIG_V850) +#if (!defined(__ia64__) && !defined(CONFIG_V850)) || defined(CONFIG_COMPAT) /* * Back compatibility for getrlimit. Needed for some apps. diff -Nru a/mm/memory.c b/mm/memory.c --- a/mm/memory.c Thu Jun 19 00:45:34 2003 +++ b/mm/memory.c Thu Jun 19 00:45:34 2003 @@ -114,8 +114,10 @@ } pmd = pmd_offset(dir, 0); pgd_clear(dir); - for (j = 0; j < PTRS_PER_PMD ; j++) + for (j = 0; j < PTRS_PER_PMD ; j++) { + prefetchw(pmd + j + PREFETCH_STRIDE/sizeof(*pmd)); free_one_pmd(tlb, pmd+j); + } pmd_free_tlb(tlb, pmd); }